新增删除

This commit is contained in:
2025-08-25 14:50:39 +08:00
parent ff46d9065f
commit d0c8c86839
8 changed files with 159 additions and 18 deletions

View File

@@ -21,7 +21,7 @@ srs:
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080 正式8085 测试8088
port: 8085
port: 8088
servlet:
# 应用的访问路径
context-path: /

View File

@@ -55,6 +55,14 @@ public interface CphMsgMapper extends BaseMapper<CphMsg>
*/
public int deleteCphMsgById(Long id);
/**
* 根据接收人和内容中的标识来查找流程消息 (使用LIKE查询) 知无涯
*
* @param cphMsg 包含 receiver 和 content (作为模糊查询的标识) 的查询对象
* @return 匹配的消息列表
*/
public List<CphMsg> selectCphMsgListForFlowable(CphMsg cphMsg);
/**
* 批量删除消息
*

View File

@@ -59,6 +59,14 @@ public interface ICphMsgService
*/
public int deleteCphMsgById(Long id);
/**
* 删除消息信息 精准匹配版
*
* @param cphMsg 消息
* @return 列表
*/
List<CphMsg> selectCphMsgListForFlowable(CphMsg cphMsg);
/**
* 根据学号查询用户ID
*

View File

@@ -95,6 +95,16 @@ public class CphMsgServiceImpl extends ServiceImpl<CphMsgMapper,CphMsg> implemen
{
return cphMsgMapper.deleteCphMsgById(id);
}
/**
* 删除消息信息
*
* @param cphMsg 消息
* @return 结果
*/
@Override
public List<CphMsg> selectCphMsgListForFlowable(CphMsg cphMsg) {
return cphMsgMapper.selectCphMsgListForFlowable(cphMsg);
}
/**
* 根据学号查询用户ID

View File

@@ -84,4 +84,16 @@
<select id="getUserIdByStuNo" parameterType="String" resultType="Long">
select user_id from sys_user where user_name = #{stuNo}
</select>
<select id="selectCphMsgListForFlowable" parameterType="CphMsg" resultMap="CphMsgResult">
<include refid="selectCphMsgVo"/>
<where>
<if test="receiver != null "> and receiver = #{receiver}</if>
<if test="content != null and content != ''">
and content LIKE CONCAT('%', #{content}, '%')
</if>
</where>
order by id desc
</select>
</mapper>

View File

@@ -13,14 +13,14 @@ import java.util.Collections;
import java.util.List;
/**
* 【通用线上监听器】为即将到来的任务创建内部“我的消息”记录。
* 【通用线上监听器】为即将到来的任务创建内部“我的消息”记录。 知无涯1
* <p>
* 该监听器被设计为在SequenceFlow的'take'事件上触发。
* 它会智能地从流程变量中读取单个接收人(变量名: approval)或多个接收人(变量名: userList)
* 然后为每一位接收人创建一条内部消息。
* </p>
*/
@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<Long> 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 + "】待办任务需要处理,<a href='http://zhxg.gxsdxy.cn/web/#/pages/Approval/index'>请点击前往处理</a>。";
// --- 关键改动:构建带有隐藏标识的消息内容 ---
String messageText = "您有一条新的【" + taskName + "】待办任务需要处理,";
// 我们嵌入一个隐藏的span它包含了流程实例ID和活动ID作为唯一标识
String hiddenIdentifier = String.format("<span id='flow-identifier' data-proc-inst-id='%s' data-activity-id='%s' style='display:none;'></span>",
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);
}
}

View File

@@ -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;
/**
* 【任务监听器】在任务完成后,删除内部消息。
* <p>
* 该监听器被设计为在UserTask的'complete'事件上触发。
* 它通过解析消息内容中的隐藏HTML标识来找到与当前已完成任务关联的消息
* 并将其删除。
* </p>
*/
@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<CphMsg> 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);
}
}
}

View File

@@ -265,7 +265,7 @@ public class RtStuDisciplinaryApplicationServiceImpl extends ServiceImpl<RtStuDi
// todo 企业微信推送消息
AjaxResult ajaxResult = flowDefinitionService.startProcessInstanceById("flow_n27gxm4k:20:710023", variables);
AjaxResult ajaxResult = flowDefinitionService.startProcessInstanceById("flow_n27gxm4k:22:720004", variables);
String code = ajaxResult.get("code").toString();
if (code.equals("200")) {