feat(xispeak): 部门审批信息改为持久化到业务表单JSON,不再依赖流程引擎变量
- DeptApproveDetail 新增 isEnd/implWorker 字段 - 新增 saveSubApprove 接口,直接写入 approveInfo JSON - XiSpeakFlow: getImplDeptLeaderIsEnd/getDeptWorkerList 改为 JSON 优先 + 流程变量兜底,兼容旧流程实例 - XiSpeakFlow: 新增 getImplDeptIsEnd(execution, deptId) 流程表达式 - XiSpeakFeedbackFlow: 新增 getImplDeptIsEnd/getImplLeaderAsWorker,提炼公共 getDeptApproveDetailByTask - FlowNodeExpression: 新增 getSonProcessVariableInt/getSonProcessVariableBoolean 类型安全工具方法 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -42,5 +42,6 @@ public class XiSpeakConfig {
|
||||
private String temImplLeaderKey;
|
||||
private String temBgLeaderKey;
|
||||
private String sdwLeaderListKey;
|
||||
private String isEndKey;
|
||||
}
|
||||
}
|
||||
|
||||
+94
-44
@@ -10,6 +10,9 @@ import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
|
||||
import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetail;
|
||||
import org.jeecg.modules.bg.xispeak.service.IBgXiSpeakService;
|
||||
import org.jeecg.modules.extbpm.process.common.expression.FlowNodeExpression;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -26,6 +29,7 @@ public class XiSpeakFlow {
|
||||
private final ISysBaseAPI iSysBaseAPI;
|
||||
private final RuntimeService runtimeService;
|
||||
private final FlowNodeExpression flowNodeExpression;
|
||||
private final IBgXiSpeakService bgXiSpeakService;
|
||||
|
||||
//流程表达式内用法 ${xiSpeakFlow.getBgDeptLdUserIdList()}
|
||||
public List<String> getBgDeptLdUserIdList() {
|
||||
@@ -194,25 +198,6 @@ public class XiSpeakFlow {
|
||||
return flowNodeExpression.getSonProcessHqVariableList(execution,xiSpeakConfig.getXiSpeak().getTemImplWorkerKey()).size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getIsEnd(execution)}
|
||||
*/
|
||||
public int getIsEnd(DelegateExecution execution) {
|
||||
Object value = flowNodeExpression.getSonProcessHqVariable(execution, "isEnd");
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(String.valueOf(value));
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("isEnd变量值无法解析为int: {}", value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemImplLeaderList(execution)}
|
||||
*/
|
||||
@@ -242,10 +227,48 @@ public class XiSpeakFlow {
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemBgLeaderListLength(execution)}
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getImplDeptLeaderIsEnd(execution)=='1'}
|
||||
* 优先从业务表单 JSON 读取,没有则回退到流程变量(兼容旧流程实例)
|
||||
*/
|
||||
public int getImplDeptLeaderIsEnd(DelegateExecution execution) {
|
||||
return flowNodeExpression.getSonProcessHqVariableList(execution,xiSpeakConfig.getXiSpeak().getTemBgLeaderKey());
|
||||
public String getImplDeptLeaderIsEnd(DelegateExecution execution) {
|
||||
DeptApproveDetail detail = getDeptApproveDetail(execution);
|
||||
if (detail != null && detail.getIsEnd() != null) {
|
||||
return String.valueOf(detail.getIsEnd());
|
||||
}
|
||||
// 兜底:从流程变量读取(兼容旧流程)
|
||||
Object value = flowNodeExpression.getSonProcessVariable(execution, xiSpeakConfig.getXiSpeak().getIsEndKey());
|
||||
return value == null ? "0" : value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getImplDeptLeader(execution)}
|
||||
*/
|
||||
public String getImplDeptLeader(DelegateExecution execution) {
|
||||
DeptApproveDetail detail = getDeptApproveDetail(execution);
|
||||
if (detail != null && detail.getIsEnd() != null) {
|
||||
return String.valueOf(detail.getImplWorker());
|
||||
}
|
||||
return detail == null ? StringUtils.EMPTY_STRING : detail.getImplWorker();
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getImplDeptWorkerListFromJson(execution)}
|
||||
* 优先从业务表单 JSON 读取,没有则回退到流程变量(兼容旧流程实例)
|
||||
*/
|
||||
public List<String> getImplDeptWorkerListFromJson(DelegateExecution execution) {
|
||||
DeptApproveDetail detail = getDeptApproveDetail(execution);
|
||||
if (detail != null && detail.getIsEnd() != null) {
|
||||
return detail.getImplUserNameList();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getImplDeptWorkerListLengthFromJson(execution)}
|
||||
* 优先从业务表单 JSON 读取,没有则回退到流程变量(兼容旧流程实例)
|
||||
*/
|
||||
public int getImplDeptWorkerListLengthFromJson(DelegateExecution execution) {
|
||||
return this.getImplDeptWorkerListFromJson(execution).size();
|
||||
}
|
||||
|
||||
|
||||
@@ -258,6 +281,35 @@ public class XiSpeakFlow {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 从执行实例中获取当前部门ID并查询业务表单 JSON 中的部门审批详情。
|
||||
*/
|
||||
private DeptApproveDetail getDeptApproveDetail(DelegateExecution execution) {
|
||||
if (execution == null) {
|
||||
return null;
|
||||
}
|
||||
String businessKey = java.util.Objects.toString(
|
||||
execution.getVariable(xiSpeakConfig.getXiSpeak().getBusinessKey()), null);
|
||||
String implDeptKey = xiSpeakConfig.getXiSpeak().getImplDeptCollectionUsedKey();
|
||||
Object rawDeptVar = execution.getVariableLocal(implDeptKey);
|
||||
if (rawDeptVar == null) {
|
||||
rawDeptVar = execution.getVariable(implDeptKey);
|
||||
}
|
||||
if (org.apache.commons.lang.StringUtils.isBlank(businessKey) || rawDeptVar == null) {
|
||||
return null;
|
||||
}
|
||||
String deptId = rawDeptVar.toString().replace("[", "").replace("]", "").trim();
|
||||
BgXiSpeak xiSpeak = bgXiSpeakService.getById(businessKey);
|
||||
if (xiSpeak == null || xiSpeak.getApproveInfo() == null) {
|
||||
return null;
|
||||
}
|
||||
return xiSpeak.getApproveInfo().get(deptId);
|
||||
}
|
||||
// 流程表达式用法${xiSpeakFlow.getImplDeptIsEnd(execution)==1}
|
||||
public int getImplDeptIsEnd(DelegateExecution execution){
|
||||
return getDeptApproveDetail(execution).getIsEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽取出的公共逻辑:从当前执行实例获取局部变量并转为字符串
|
||||
*/
|
||||
@@ -341,42 +393,40 @@ public class XiSpeakFlow {
|
||||
return resultList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 优先从业务表单 JSON 读取 implUserNameList / implWorker,没有则回退到流程变量(兼容旧流程实例)
|
||||
*/
|
||||
public List<String> getDeptWorkerList(DelegateExecution execution) {
|
||||
DeptApproveDetail detail = getDeptApproveDetail(execution);
|
||||
if (detail != null) {
|
||||
// isEnd=0 时读取 implUserNameList
|
||||
if (detail.getImplUserNameList() != null && !detail.getImplUserNameList().isEmpty()) {
|
||||
return detail.getImplUserNameList();
|
||||
}
|
||||
// isEnd=1 时读取 implWorker(兼容旧数据)
|
||||
if (org.apache.commons.lang.StringUtils.isNotBlank(detail.getImplWorker())) {
|
||||
return Collections.singletonList(detail.getImplWorker());
|
||||
}
|
||||
}
|
||||
// 兜底:从流程变量读取(兼容旧流程)
|
||||
String variableName = xiSpeakConfig.getXiSpeak().getDeptWorkerKey();
|
||||
if (execution == null || org.apache.commons.lang.StringUtils.isBlank(variableName)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 优先尝试从当前 Execution 的局部作用域获取
|
||||
// 在多实例(会签)中,每个分支特有的变量(如 item 变量)通常存储在这里
|
||||
Object value = execution.getVariableLocal(variableName);
|
||||
|
||||
// 2. 如果局部没有,直接使用 getVariable 获取
|
||||
// 该方法会自动向上追溯:当前 Execution -> 父 Execution -> 流程实例(Global)
|
||||
if (value == null) {
|
||||
value = execution.getVariable(variableName);
|
||||
}
|
||||
|
||||
// 3. 结果处理
|
||||
if (value != null) {
|
||||
return splitUsernames(value);
|
||||
return Arrays.stream(String.valueOf(value).split(SymbolConstant.COMMA))
|
||||
.map(String::trim)
|
||||
.filter(org.apache.commons.lang.StringUtils::isNotBlank)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("getSonProcessVariable 失败, executionId={}, variableName={}",
|
||||
execution.getId(), variableName, e);
|
||||
log.warn("getDeptWorkerList from process variable failed", e);
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
private List<String> splitUsernames(Object value) {
|
||||
if (value == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Arrays.stream(String.valueOf(value).split(SymbolConstant.COMMA))
|
||||
.map(String::trim)
|
||||
.filter(org.apache.commons.lang.StringUtils::isNotBlank)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+50
@@ -115,6 +115,56 @@ public class XiSpeakFeedbackFlow {
|
||||
.orElse("");
|
||||
}
|
||||
|
||||
// 流程表达式内用法 ${XiSpeakFeedbackFlow.getImplDeptIsEnd(execution)}
|
||||
public Integer getImplDeptIsEnd(DelegateExecution execution) {
|
||||
DeptApproveDetail detail = getDeptApproveDetailByTask(execution);
|
||||
if (detail == null || detail.getIsEnd() == null) {
|
||||
return 0;
|
||||
}
|
||||
return detail.getIsEnd();
|
||||
}
|
||||
|
||||
// 流程表达式内用法 ${XiSpeakFeedbackFlow.getImplLeaderAsWorker(execution)}
|
||||
public String getImplLeaderAsWorker(DelegateExecution execution) {
|
||||
DeptApproveDetail detail = getDeptApproveDetailByTask(execution);
|
||||
if (detail == null || StringUtils.isBlank(detail.getImplWorker())) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return detail.getImplWorker();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 execution 获取 businessKey → TaskTask → BgXiSpeak → DeptApproveDetail
|
||||
*/
|
||||
private DeptApproveDetail getDeptApproveDetailByTask(DelegateExecution execution) {
|
||||
String businessKey = execution.getProcessInstanceBusinessKey();
|
||||
|
||||
if (StringUtils.isBlank(businessKey)) {
|
||||
log.warn("流程 BusinessKey 缺失,ExecutionId: {}", execution.getId());
|
||||
return null;
|
||||
}
|
||||
|
||||
TaskTask taskTask = taskTaskService.getById(businessKey);
|
||||
if (taskTask == null || StringUtils.isBlank(taskTask.getBusinessId())) {
|
||||
log.warn("无法获取任务数据或业务关联ID![taskTaskId: {}]", businessKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
BgXiSpeak xiSpeak = bgXiSpeakService.getById(taskTask.getBusinessId());
|
||||
if (xiSpeak == null || xiSpeak.getApproveInfo() == null) {
|
||||
log.warn("业务表单数据或审批配置缺失![xiBusinessId: {}]", taskTask.getBusinessId());
|
||||
return null;
|
||||
}
|
||||
|
||||
String deptId = taskTask.getDeptId();
|
||||
if (StringUtils.isBlank(deptId)) {
|
||||
log.warn("中间表表单部门信息缺失![tasktaskId: {}]", taskTask.getId());
|
||||
return null;
|
||||
}
|
||||
|
||||
return xiSpeak.getApproveInfo().get(deptId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前流程的经办部门的经办人。
|
||||
* <p>用于流程表达式判断,通过 BusinessKey 关联业务主键,获取当前经办人。</p>
|
||||
|
||||
@@ -17,6 +17,7 @@ flow-biz:
|
||||
tem-impl-leader-key: "tem_impl_leader"
|
||||
tem-bg-leader-key: "tem_bg_leader"
|
||||
sdw-leader-list-key: "sdwLeaderList"
|
||||
is-end-key: "isEnd"
|
||||
xi-speak-fb:
|
||||
dept-id: "x"
|
||||
business-id: "business_id"
|
||||
|
||||
Reference in New Issue
Block a user