补全AfterImplDeptLeaderApproveFeedbackListener监听器
This commit is contained in:
+91
-3
@@ -2,21 +2,26 @@ package org.jeecg.xispeakfb.listener;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.flowable.engine.delegate.TaskListener;
|
import org.flowable.engine.delegate.TaskListener;
|
||||||
import org.flowable.task.service.delegate.DelegateTask;
|
import org.flowable.task.service.delegate.DelegateTask;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
|
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
|
||||||
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeakFeedback;
|
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeakFeedback;
|
||||||
|
import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetail;
|
||||||
|
import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetailMap;
|
||||||
import org.jeecg.modules.bg.xispeak.service.IBgXiSpeakFeedbackService;
|
import org.jeecg.modules.bg.xispeak.service.IBgXiSpeakFeedbackService;
|
||||||
|
import org.jeecg.modules.bg.xispeak.service.IBgXiSpeakService;
|
||||||
import org.jeecg.modules.tasktask.constant.FlowConstants;
|
import org.jeecg.modules.tasktask.constant.FlowConstants;
|
||||||
import org.jeecg.modules.tasktask.entity.TaskTask;
|
import org.jeecg.modules.tasktask.entity.TaskTask;
|
||||||
import org.jeecg.modules.tasktask.service.ITaskTaskService;
|
import org.jeecg.modules.tasktask.service.ITaskTaskService;
|
||||||
|
import org.jeecg.xispeak.XiSpeakConfig;
|
||||||
import org.jeecg.xispeakfb.XiSpeakFeedbackConfig;
|
import org.jeecg.xispeakfb.XiSpeakFeedbackConfig;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component("AfterImplDeptLeaderApproveFeedbackListener")
|
@Component("AfterImplDeptLeaderApproveFeedbackListener")
|
||||||
@@ -24,13 +29,96 @@ import java.util.Map;
|
|||||||
public class AfterImplDeptLeaderApproveListener implements TaskListener {
|
public class AfterImplDeptLeaderApproveListener implements TaskListener {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final XiSpeakFeedbackConfig xiSpeakFeedbackConfig;
|
private final XiSpeakFeedbackConfig xiSpeakFeedbackConfig;
|
||||||
private final IBgXiSpeakFeedbackService bgXiSpeakFeedbackService;
|
private final IBgXiSpeakFeedbackService bgXiSpeakFeedbackService;
|
||||||
private final ITaskTaskService taskTaskService;
|
private final ITaskTaskService taskTaskService;
|
||||||
|
private final XiSpeakConfig xiSpeakConfig;
|
||||||
|
private final IBgXiSpeakService bgXiSpeakService;
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void notify(DelegateTask delegateTask) {
|
public void notify(DelegateTask delegateTask) {
|
||||||
|
String currentWorkerName = delegateTask.getAssignee();
|
||||||
|
Object rawBusinessKey = delegateTask.getVariable(xiSpeakConfig.getXiSpeak().getBusinessKey());
|
||||||
|
String taskId = delegateTask.getId();
|
||||||
|
|
||||||
|
// 1. 基础边界防御性校验
|
||||||
|
if (StringUtils.isEmpty(currentWorkerName) || rawBusinessKey == null) {
|
||||||
|
log.warn("【任务通知】无法获取有效的审批人或业务ID,略过处理。TaskId: {}, Assignee: {}, BusinessKey: {}",
|
||||||
|
taskId, currentWorkerName, rawBusinessKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String businessKeyStr = rawBusinessKey.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 2. 🎯 架构优化:移除 FOR UPDATE 悲观锁,改用普通查询,预防工作流交叉死锁
|
||||||
|
BgXiSpeak xiSpeak = bgXiSpeakService.getById(businessKeyStr);
|
||||||
|
if (xiSpeak == null) {
|
||||||
|
log.error("【任务通知】业务数据不存在,终止处理。BusinessKey: {}", businessKeyStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 部门变量安全解析
|
||||||
|
String implDeptKey = xiSpeakConfig.getXiSpeak().getImplDeptCollectionUsedKey();
|
||||||
|
Object rawDeptVar = delegateTask.getVariableLocal(implDeptKey);
|
||||||
|
if (rawDeptVar == null) {
|
||||||
|
rawDeptVar = delegateTask.getVariable(implDeptKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawDeptVar == null) {
|
||||||
|
log.error("【任务通知】流程数据异常:未找到实施部门ID变量: {}, BusinessKey: {}", implDeptKey, businessKeyStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🎯 优化:更安全的解析机制
|
||||||
|
String cleanDeptId = parseDeptId(rawDeptVar);
|
||||||
|
|
||||||
|
// 4. 安全获取或创建部门审批详情
|
||||||
|
DeptApproveDetailMap approveMap = xiSpeak.getApproveInfo();
|
||||||
|
if (approveMap == null) {
|
||||||
|
approveMap = new DeptApproveDetailMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
DeptApproveDetail detail = approveMap.get(cleanDeptId);
|
||||||
|
if (detail == null) {
|
||||||
|
detail = new DeptApproveDetail();
|
||||||
|
detail.setDeptId(cleanDeptId);
|
||||||
|
detail.setImplUserNameList(new ArrayList<>());
|
||||||
|
approveMap.put(cleanDeptId, detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 状态比对与幂等更新
|
||||||
|
if (!Objects.equals(detail.getApproverName(), currentWorkerName)) {
|
||||||
|
detail.setApproverName(currentWorkerName);
|
||||||
|
|
||||||
|
// 写回并更新
|
||||||
|
xiSpeak.setApproveInfo(approveMap);
|
||||||
|
bgXiSpeakService.updateById(xiSpeak);
|
||||||
|
|
||||||
|
log.info("【任务通知】业务单据 [{}] 部门 [{}] 经办人审批记录成功更新为: {}",
|
||||||
|
businessKeyStr, cleanDeptId, currentWorkerName);
|
||||||
|
} else {
|
||||||
|
log.info("【任务通知】业务单据 [{}] 部门 [{}] 经办人未发生变化 [{}], 跳过数据库更新",
|
||||||
|
businessKeyStr, cleanDeptId, currentWorkerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 6. 异常全上下文捕获,方便线上无缝排查
|
||||||
|
log.error(String.format("【任务通知】处理任务结束监听器异常。TaskId: %s, BusinessKey: %s", taskId, businessKeyStr), e);
|
||||||
|
throw e; // 抛出异常以触发 Spring 事务和 Flowable 流程回滚
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 辅助方法:安全解析部门ID,支持 Collection 和 String 表现形式
|
||||||
|
*/
|
||||||
|
private String parseDeptId(Object rawDeptVar) {
|
||||||
|
if (rawDeptVar instanceof Collection) {
|
||||||
|
Collection<?> collection = (Collection<?>) rawDeptVar;
|
||||||
|
if (!collection.isEmpty()) {
|
||||||
|
return Objects.toString(collection.iterator().next(), "").trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rawDeptVar.toString().replace("[", "").replace("]", "").trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user