!22 wsm-xispeak-收集后反馈流程
Merge pull request !22 from new_new_new/feature/20260515
This commit is contained in:
@@ -37,5 +37,9 @@ public class XiSpeakConfig {
|
||||
private String deptWorkerKey;
|
||||
private String xiSpeakFbFlowCode;
|
||||
private String formUrl;
|
||||
private String feedbackRightNowCode;
|
||||
private String temImplWorkerKey;
|
||||
private String temImplLeaderKey;
|
||||
private String temBgLeaderKey;
|
||||
}
|
||||
}
|
||||
|
||||
+110
-14
@@ -4,11 +4,13 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.shiro.util.StringUtils;
|
||||
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.extbpm.process.common.expression.FlowNodeExpression;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -23,6 +25,7 @@ public class XiSpeakFlow {
|
||||
private final XiSpeakConfig xiSpeakConfig;
|
||||
private final ISysBaseAPI iSysBaseAPI;
|
||||
private final RuntimeService runtimeService;
|
||||
private final FlowNodeExpression flowNodeExpression;
|
||||
|
||||
//流程表达式内用法 ${xiSpeakFlow.getBgDeptLdUserIdList()}
|
||||
public List<String> getBgDeptLdUserIdList() {
|
||||
@@ -67,37 +70,129 @@ public class XiSpeakFlow {
|
||||
return getBgDeptLdUserIdList().size();
|
||||
}
|
||||
|
||||
public Integer getNeedSdwApproval(Object jsonData) {
|
||||
XiSpeakConfig.XiSpeakProperties props = xiSpeakConfig.getXiSpeak();
|
||||
if (jsonData == null || org.apache.commons.lang.StringUtils.isBlank(props.getNeedSdwApproveCode())) {
|
||||
/**
|
||||
* 提取后的公共解析方法
|
||||
* @param jsonData 原始数据对象
|
||||
* @param codeName 配置项对应的 Key
|
||||
* @param logLabel 日志标识名(用于区分不同业务的日志输出)
|
||||
*/
|
||||
private Integer getCodeValueFromData(Object jsonData, String codeName, String logLabel) {
|
||||
// 1. 基础校验:如果配置的 Key 为空,直接返回 0
|
||||
if (jsonData == null || org.apache.commons.lang.StringUtils.isBlank(codeName)) {
|
||||
return 0;
|
||||
}
|
||||
String codeName = props.getNeedSdwApproveCode();
|
||||
if (org.apache.commons.lang.StringUtils.isBlank(codeName)) return 0;
|
||||
|
||||
try {
|
||||
JSONObject data;
|
||||
// 2. 统一转换为 JSONObject (此处逻辑复用)
|
||||
if (jsonData instanceof JSONObject) {
|
||||
data = (JSONObject) jsonData;
|
||||
} else if (jsonData instanceof String) {
|
||||
if (org.apache.commons.lang.StringUtils.isBlank((String) jsonData)) {
|
||||
return 0;
|
||||
}
|
||||
data = JSONObject.parseObject((String) jsonData);
|
||||
String jsonStr = (String) jsonData;
|
||||
if (org.apache.commons.lang.StringUtils.isBlank(jsonStr)) return 0;
|
||||
data = JSONObject.parseObject(jsonStr);
|
||||
} else {
|
||||
// 处理普通 POJO 对象
|
||||
data = JSONObject.parseObject(JSONObject.toJSONString(jsonData));
|
||||
}
|
||||
int finalResult = Optional.ofNullable(data)
|
||||
.map(d -> d.getInteger(codeName))
|
||||
.orElse(0);
|
||||
|
||||
log.info("needSdwApproval结果为{}", finalResult);
|
||||
// 3. 提取结果
|
||||
Integer result = data.getInteger(codeName);
|
||||
int finalResult = (result == null) ? 0 : result;
|
||||
|
||||
log.info("{} 业务解析结果: {}", logLabel, finalResult);
|
||||
return finalResult;
|
||||
} catch (Exception e) {
|
||||
log.warn("getJsondata parse failed, codeName={}, jsonData={}", codeName, jsonData, e);
|
||||
log.warn("JSON解析失败: 业务={}, codeKey={}, 数据={}", logLabel, codeName, jsonData, e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// --- 调用处 ---
|
||||
|
||||
//流程表达式内用法${xiSpeakFlow.getNeedSdwApproval(jsonData)}
|
||||
public Integer getNeedSdwApproval(Object jsonData) {
|
||||
String codeName = xiSpeakConfig.getXiSpeak().getNeedSdwApproveCode();
|
||||
return getCodeValueFromData(jsonData, codeName, "需SDW审批");
|
||||
}
|
||||
|
||||
//流程表达式内用法${xiSpeakFlow.getFeedBackRightNow(jsonData)}
|
||||
public Integer getFeedBackRightNow(Object jsonData) {
|
||||
String codeName = xiSpeakConfig.getXiSpeak().getFeedbackRightNowCode();
|
||||
return getCodeValueFromData(jsonData, codeName, "立即反馈");
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemImplWorkerList(execution)}
|
||||
*/
|
||||
public List<String> getTemImplWorkerList(DelegateExecution execution) {
|
||||
return flowNodeExpression.getSonProcessHqVariableList(execution,xiSpeakConfig.getXiSpeak().getTemImplWorkerKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemImplWorkerListLength(execution)}
|
||||
*/
|
||||
public int getTemImplWorkerListLength(DelegateExecution execution) {
|
||||
return flowNodeExpression.getSonProcessHqVariableList(execution,xiSpeakConfig.getXiSpeak().getTemImplWorkerKey()).size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemImplLeaderList(execution)}
|
||||
*/
|
||||
public List<String> getTemImplLeaderList(DelegateExecution execution) {
|
||||
return flowNodeExpression.getSonProcessHqVariableList(execution,xiSpeakConfig.getXiSpeak().getTemImplLeaderKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemImplLeaderListLength(execution)}
|
||||
*/
|
||||
public int getTemImplLeaderListLength(DelegateExecution execution) {
|
||||
return flowNodeExpression.getSonProcessHqVariableList(execution,xiSpeakConfig.getXiSpeak().getTemImplLeaderKey()).size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemBgLeaderList(execution)}
|
||||
*/
|
||||
public List<String> getTemBgLeaderList(DelegateExecution execution) {
|
||||
return flowNodeExpression.getSonProcessHqVariableList(execution,xiSpeakConfig.getXiSpeak().getTemBgLeaderKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemBgLeaderListLength(execution)}
|
||||
*/
|
||||
public int getTemBgLeaderListLength(DelegateExecution execution) {
|
||||
return flowNodeExpression.getSonProcessHqVariableList(execution,xiSpeakConfig.getXiSpeak().getTemBgLeaderKey()).size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 流程表达式内用法: ${xiSpeakFlow.getTemBgLeader(execution)}
|
||||
*/
|
||||
public String getTemBgLeader(DelegateExecution execution) {
|
||||
return getLocalVarAsString(execution, xiSpeakConfig.getXiSpeak().getTemBgLeaderKey());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 抽取出的公共逻辑:从当前执行实例获取局部变量并转为字符串
|
||||
*/
|
||||
private String getLocalVarAsString(DelegateExecution execution, String variableKey) {
|
||||
if (execution == null || org.apache.commons.lang3.StringUtils.isBlank(variableKey)) {
|
||||
return StringUtils.EMPTY_STRING;
|
||||
}
|
||||
|
||||
// 在 DelegateExecution 环境下,getId() 永远不为空,直接取变量即可
|
||||
Object obj = execution.getVariableLocal(variableKey);
|
||||
|
||||
if (obj instanceof String) {
|
||||
return (String) obj;
|
||||
}
|
||||
|
||||
// 如果变量不存在或类型不对,返回空字符串(防止流程引擎解析报错)
|
||||
return StringUtils.EMPTY_STRING;
|
||||
}
|
||||
|
||||
public List<String> getImplDeptLdsList(String deptId) {
|
||||
return iSysBaseAPI.getUsersListByDeptIdAndRoleIdLocalApi(deptId, xiSpeakConfig.getXiSpeak().getLdRoleId());
|
||||
}
|
||||
@@ -199,4 +294,5 @@ public class XiSpeakFlow {
|
||||
.filter(org.apache.commons.lang.StringUtils::isNotBlank)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package org.jeecg.xispeak.listener;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.tasktask.entity.TaskTask;
|
||||
import org.jeecg.modules.tasktask.service.ITaskTaskService;
|
||||
import org.jeecg.xispeak.XiSpeakConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component("AfterBgLeaderApproveListener")
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
public class AfterBgLeaderApproveListener implements TaskListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final FlowNodeExpression flowNodeExpression;
|
||||
private final RuntimeService runtimeService;
|
||||
private final XiSpeakConfig xiSpeakConfig;
|
||||
private final ITaskTaskService taskTaskService;
|
||||
private final IBgXiSpeakService bgXiSpeakService;
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
|
||||
XiSpeakConfig.XiSpeakProperties props = xiSpeakConfig.getXiSpeak();
|
||||
|
||||
if (delegateTask == null) return;
|
||||
|
||||
String assignee = delegateTask.getAssignee();
|
||||
if (StringUtils.isBlank(assignee)) return;
|
||||
|
||||
String currentExecutionId = delegateTask.getExecutionId();
|
||||
if (StringUtils.isBlank(currentExecutionId)) return;
|
||||
|
||||
// 2. 先通过 runtimeService 查询当前的执行实例对象
|
||||
Execution currentExecution = runtimeService.createExecutionQuery()
|
||||
.executionId(currentExecutionId)
|
||||
.singleResult();
|
||||
|
||||
if (currentExecution == null) return;
|
||||
|
||||
// 2. 向上寻找第一层父级 (比如:内层会签容器/子流程)
|
||||
String parentId = currentExecution.getParentId();
|
||||
if (StringUtils.isBlank(parentId)) {
|
||||
log.warn("无法找到父级执行实例,当前已是顶层");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 核心:通过 runtimeService 获取第一层父级的实体对象,从而拿到第二层的 ID
|
||||
// 只有拿到实体对象,才能调用 getParentId() 继续向上爬
|
||||
Execution parentExecution = runtimeService.createExecutionQuery()
|
||||
.executionId(parentId)
|
||||
.singleResult();
|
||||
|
||||
if (parentExecution != null) {
|
||||
// 4. 获取第二层父级 ID (大会签容器/外层作用域)
|
||||
String grandParentId = parentExecution.getParentId();
|
||||
|
||||
// 5. 确定最终存储目标
|
||||
// 如果有第二层父级,则存入第二层;如果没有,则退而求其次存入第一层
|
||||
String targetId = StringUtils.isNotBlank(grandParentId) ? grandParentId : parentId;
|
||||
|
||||
try {
|
||||
// 6. 执行存储
|
||||
runtimeService.setVariableLocal(targetId, props.getTemBgLeaderKey() , assignee);
|
||||
|
||||
log.info("变量已存入向上两层级:TargetId={}, OriginalId={}, Assignee={}",
|
||||
targetId, currentExecution.getId(), assignee);
|
||||
} catch (Exception e) {
|
||||
log.error("设置嵌套局部变量失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
-32
@@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
|
||||
import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetail;
|
||||
import org.jeecg.modules.bg.xispeak.service.IBgXiSpeakService;
|
||||
@@ -31,46 +33,61 @@ import java.util.stream.Collectors;
|
||||
public class AfterImplDeptLeaderApproveListener implements TaskListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final FlowNodeExpression flowNodeExpression;
|
||||
private final RuntimeService runtimeService;
|
||||
private final XiSpeakConfig xiSpeakConfig;
|
||||
private final ITaskTaskService taskTaskService;
|
||||
private final IBgXiSpeakService bgXiSpeakService;
|
||||
private static final String VARIABLE_NAME = "tem_impl_leader";
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
private static RuntimeService runtimeService;
|
||||
|
||||
static {
|
||||
runtimeService = SpringContextUtils.getBean(RuntimeService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
// 1. 获取基础数据
|
||||
String currentAssignee = delegateTask.getAssignee();
|
||||
Object rawTaskTaskId = delegateTask.getVariable(xiSpeakConfig.getXiSpeak().getBusinessKey());
|
||||
String implDeptKey = xiSpeakConfig.getXiSpeak().getImplDeptCollectionUsedKey();
|
||||
String rawDeptVar = delegateTask.getVariable(implDeptKey).toString();
|
||||
String cleanDeptId = rawDeptVar.replace("[", "").replace("]", "").trim();
|
||||
if (delegateTask == null) return;
|
||||
|
||||
// 2. 【核心】使用行锁查询,确保拿到的是数据库此刻最真实、最新的数据
|
||||
// 同时也让其他并发的审批线程在这里“排队”等待
|
||||
BgXiSpeak xiSpeak = bgXiSpeakService.getByIdForUpdate(rawTaskTaskId.toString());
|
||||
if (xiSpeak == null) return;
|
||||
String assignee = delegateTask.getAssignee();
|
||||
if (StringUtils.isBlank(assignee)) return;
|
||||
|
||||
// 3. 操作 Map
|
||||
Map<String, DeptApproveDetail> map = xiSpeak.getApproveInfo();
|
||||
if (map == null) map = new HashMap<>();
|
||||
String currentExecutionId = delegateTask.getExecutionId();
|
||||
if (StringUtils.isBlank(currentExecutionId)) return;
|
||||
|
||||
// 4. 获取或创建详情对象
|
||||
// 使用你定义的 POJO
|
||||
DeptApproveDetail detail = map.getOrDefault(cleanDeptId, new DeptApproveDetail());
|
||||
// 2. 先通过 runtimeService 查询当前的执行实例对象
|
||||
Execution currentExecution = runtimeService.createExecutionQuery()
|
||||
.executionId(currentExecutionId)
|
||||
.singleResult();
|
||||
|
||||
// 只有没审批过才记录(防止重复触发覆盖已有数据)
|
||||
if (StringUtils.isBlank(detail.getApproverName())) {
|
||||
detail.setDeptId(cleanDeptId);
|
||||
detail.setApproverName(currentAssignee);
|
||||
// 这里可以根据需要设置其他字段,比如 detail.setApproverId(...)
|
||||
if (currentExecution == null) return;
|
||||
|
||||
map.put(cleanDeptId, detail);
|
||||
xiSpeak.setApproveInfo(map);
|
||||
// 2. 向上寻找第一层父级 (比如:内层会签容器/子流程)
|
||||
String parentId = currentExecution.getParentId();
|
||||
if (StringUtils.isBlank(parentId)) {
|
||||
log.warn("无法找到父级执行实例,当前已是顶层");
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. 写回数据库
|
||||
// 因为有了 FOR UPDATE,这里的更新绝对是基于最新数据的增量合并
|
||||
bgXiSpeakService.updateById(xiSpeak);
|
||||
// 3. 核心:通过 runtimeService 获取第一层父级的实体对象,从而拿到第二层的 ID
|
||||
// 只有拿到实体对象,才能调用 getParentId() 继续向上爬
|
||||
Execution parentExecution = runtimeService.createExecutionQuery()
|
||||
.executionId(parentId)
|
||||
.singleResult();
|
||||
|
||||
if (parentExecution != null) {
|
||||
// 4. 获取第二层父级 ID (大会签容器/外层作用域)
|
||||
String grandParentId = parentExecution.getParentId();
|
||||
|
||||
// 5. 确定最终存储目标
|
||||
// 如果有第二层父级,则存入第二层;如果没有,则退而求其次存入第一层
|
||||
String targetId = StringUtils.isNotBlank(grandParentId) ? grandParentId : parentId;
|
||||
|
||||
try {
|
||||
// 6. 执行存储
|
||||
runtimeService.setVariableLocal(targetId, VARIABLE_NAME, assignee);
|
||||
|
||||
log.info("变量已存入向上两层级:TargetId={}, OriginalId={}, Assignee={}",
|
||||
targetId, currentExecution.getId(), assignee);
|
||||
} catch (Exception e) {
|
||||
log.error("设置嵌套局部变量失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
|
||||
import org.jeecg.modules.bg.xispeak.entity.DeptApproveDetail;
|
||||
@@ -32,6 +33,7 @@ public class AfterImplWorkerApproveListener implements TaskListener {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final XiSpeakConfig xiSpeakConfig;
|
||||
private final IBgXiSpeakService bgXiSpeakService;
|
||||
private final RuntimeService runtimeService;
|
||||
|
||||
// 引入 Jackson 的 ObjectMapper 用于处理类型转换失败的情况
|
||||
private final com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
||||
@@ -39,9 +41,19 @@ public class AfterImplWorkerApproveListener implements TaskListener {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
|
||||
String currentWorkerName = delegateTask.getAssignee();
|
||||
Object rawBusinessKey = delegateTask.getVariable(xiSpeakConfig.getXiSpeak().getBusinessKey());
|
||||
|
||||
String executionId = delegateTask.getExecutionId();
|
||||
if(StringUtils.isBlank(executionId)){
|
||||
log.warn("任务通知监听器:获取执行实例ID失败,跳过流程变量设置。任务ID: {}, 办理人: {}", delegateTask.getId(), currentWorkerName);
|
||||
}else{
|
||||
runtimeService.setVariableLocal(executionId,xiSpeakConfig.getXiSpeak().getTemImplWorkerKey() , currentWorkerName);
|
||||
log.info("任务通知监听器:成功存入执行实例局部变量 -> 执行ID: [{}], 变量名: [{}], 变量值: [{}]",
|
||||
executionId, xiSpeakConfig.getXiSpeak().getTemImplWorkerKey(), currentWorkerName);
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(currentWorkerName) || rawBusinessKey == null) {
|
||||
log.warn("无法获取有效的审批人或业务ID,略过处理");
|
||||
return;
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package org.jeecg.xispeak.listener;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
|
||||
import org.jeecg.modules.tasktask.entity.TaskTask;
|
||||
import org.jeecg.modules.tasktask.service.ITaskTaskService;
|
||||
import org.jeecg.xispeak.XiSpeakConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component("AfterImplWorkerTemStoreListener")
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
public class AfterImplWorkerTemStoreListener implements TaskListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String VARIABLE_NAME = "tem_impl_worker";
|
||||
|
||||
private static RuntimeService runtimeService;
|
||||
|
||||
static {
|
||||
runtimeService = SpringContextUtils.getBean(RuntimeService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
if (delegateTask == null) return;
|
||||
|
||||
String assignee = delegateTask.getAssignee();
|
||||
if (StringUtils.isBlank(assignee)) return;
|
||||
|
||||
String currentExecutionId = delegateTask.getExecutionId();
|
||||
if (StringUtils.isBlank(currentExecutionId)) return;
|
||||
|
||||
// 2. 先通过 runtimeService 查询当前的执行实例对象
|
||||
Execution currentExecution = runtimeService.createExecutionQuery()
|
||||
.executionId(currentExecutionId)
|
||||
.singleResult();
|
||||
|
||||
if (currentExecution == null) return;
|
||||
|
||||
// 2. 向上寻找第一层父级 (比如:内层会签容器/子流程)
|
||||
String parentId = currentExecution.getParentId();
|
||||
if (StringUtils.isBlank(parentId)) {
|
||||
log.warn("无法找到父级执行实例,当前已是顶层");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 核心:通过 runtimeService 获取第一层父级的实体对象,从而拿到第二层的 ID
|
||||
// 只有拿到实体对象,才能调用 getParentId() 继续向上爬
|
||||
Execution parentExecution = runtimeService.createExecutionQuery()
|
||||
.executionId(parentId)
|
||||
.singleResult();
|
||||
|
||||
if (parentExecution != null) {
|
||||
// 4. 获取第二层父级 ID (大会签容器/外层作用域)
|
||||
String grandParentId = parentExecution.getParentId();
|
||||
|
||||
// 5. 确定最终存储目标
|
||||
// 如果有第二层父级,则存入第二层;如果没有,则退而求其次存入第一层
|
||||
String targetId = StringUtils.isNotBlank(grandParentId) ? grandParentId : parentId;
|
||||
|
||||
try {
|
||||
// 6. 执行存储
|
||||
runtimeService.setVariableLocal(targetId, VARIABLE_NAME, assignee);
|
||||
|
||||
log.info("变量已存入向上两层级:TargetId={}, OriginalId={}, Assignee={}",
|
||||
targetId, currentExecution.getId(), assignee);
|
||||
} catch (Exception e) {
|
||||
log.error("设置嵌套局部变量失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -36,7 +36,7 @@ public class XiSpeakFeedbackFlow {
|
||||
private final ITaskTaskService taskTaskService;
|
||||
|
||||
|
||||
// 流程表达式内用法 ${XiSpeakFeedbackFlow.getImplDeptList()}
|
||||
// 流程表达式内用法 ${XiSpeakFeedbackFlow.getImplDeptList(execution)}
|
||||
public List<String> getImplDeptList(DelegateExecution execution) {
|
||||
String processInstId = execution.getProcessInstanceId();
|
||||
String businessKey = execution.getProcessInstanceBusinessKey();
|
||||
@@ -66,7 +66,7 @@ public class XiSpeakFeedbackFlow {
|
||||
return deptIdList;
|
||||
}
|
||||
|
||||
// 流程表达式内用法 ${XiSpeakFeedbackFlow.getImplDeptListLength()}
|
||||
// 流程表达式内用法 ${XiSpeakFeedbackFlow.getImplDeptListLength(execution)}
|
||||
public int getImplDeptListLength(DelegateExecution execution) {
|
||||
List<String> implDeptList = this.getImplDeptList(execution);
|
||||
if (implDeptList.isEmpty() || implDeptList == null) {
|
||||
@@ -76,6 +76,7 @@ public class XiSpeakFeedbackFlow {
|
||||
return implDeptList.size();
|
||||
}
|
||||
|
||||
// 流程表达式内用法 ${XiSpeakFeedbackFlow.getImplDeptApprove(execution)}
|
||||
public String getImplDeptApprove(DelegateExecution execution) {
|
||||
String businessKey = execution.getProcessInstanceBusinessKey();
|
||||
|
||||
@@ -139,7 +140,7 @@ public class XiSpeakFeedbackFlow {
|
||||
*
|
||||
* @param execution 流程执行上下文
|
||||
* @return 经办部门经办人
|
||||
* @example 表达式用法: ${XiSpeakFeedbackFlow.getImplDeptWorker()}
|
||||
* @example 表达式用法: ${XiSpeakFeedbackFlow.getImplDeptWorker(execution)}
|
||||
*/
|
||||
public List<String> getImplDeptWorker(DelegateExecution execution) {
|
||||
String businessKey = execution.getProcessInstanceBusinessKey();
|
||||
@@ -192,7 +193,7 @@ public class XiSpeakFeedbackFlow {
|
||||
* <p>jj部门经办人</p>
|
||||
*
|
||||
* @return jj部门经办人
|
||||
* @example 表达式用法: ${XiSpeakFeedbackFlow.JJDeptWorkerList()}
|
||||
* @example 表达式用法: ${XiSpeakFeedbackFlow.getJJDeptWorkerList()}
|
||||
*/
|
||||
public List<String> getJJDeptWorkerList() {
|
||||
// 1. 安全获取配置对象
|
||||
@@ -243,7 +244,7 @@ public class XiSpeakFeedbackFlow {
|
||||
* <p>获取jj部门审核人</p>
|
||||
*
|
||||
* @return jj部门审核人
|
||||
* @example 表达式用法: ${XiSpeakFeedbackFlow.getJjDeptLeaderList()}
|
||||
* @example 表达式用法: ${XiSpeakFeedbackFlow.getJJDeptLeaderList()}
|
||||
*/
|
||||
public List<String> getJJDeptLeaderList() {
|
||||
// 1. 安全获取配置对象
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package org.jeecg.xispeakfb.listener;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
import org.flowable.task.service.delegate.DelegateTask;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeakFeedback;
|
||||
import org.jeecg.modules.bg.xispeak.service.IBgXiSpeakFeedbackService;
|
||||
import org.jeecg.modules.tasktask.constant.FlowConstants;
|
||||
import org.jeecg.modules.tasktask.entity.TaskTask;
|
||||
import org.jeecg.modules.tasktask.service.ITaskTaskService;
|
||||
import org.jeecg.xispeakfb.XiSpeakFeedbackConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component("AfterImplDeptLeaderApproveFeedbackListener")
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
public class AfterImplDeptLeaderApproveListener implements TaskListener {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final XiSpeakFeedbackConfig xiSpeakFeedbackConfig;
|
||||
private final IBgXiSpeakFeedbackService bgXiSpeakFeedbackService;
|
||||
private final ITaskTaskService taskTaskService;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ flow-biz:
|
||||
bg-dept-id: "2044677604785229826"
|
||||
ld-role-id: "2044680793306591234"
|
||||
need-sdw-approve-code: "needSdwApproval"
|
||||
feedback-right-now-code: "feedback_right_now"
|
||||
json-data-key: "json_data"
|
||||
impl-dept-key: "implDept"
|
||||
impl-dept-key-underscore-key: "impl_dept"
|
||||
@@ -12,6 +13,9 @@ flow-biz:
|
||||
dept-worker-key: "subApproveUser"
|
||||
xi-speak-fb-flowcode: "process_1778315114392"
|
||||
form-url: "bg/xispeak/components/BgXiSpeakBPMForm"
|
||||
tem-impl-worker-key: "tem_impl_worker"
|
||||
tem-impl-leader-key: "tem_impl_leader"
|
||||
tem-bg-leader-key: "tem_bg_leader"
|
||||
xi-speak-fb:
|
||||
dept-id: "x"
|
||||
business-id: "business_id"
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-system-local-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-system-biz</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
|
||||
+72
-14
@@ -9,6 +9,14 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
@@ -16,12 +24,10 @@ import org.jeecg.common.system.vo.SelectTreeModel;
|
||||
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
|
||||
import org.jeecg.modules.bg.xispeak.service.IBgXiSpeakService;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jeecg.modules.demo.bgpartymatter.entity.BgPartymatter;
|
||||
import org.jeecg.modules.bg.xispeak.dto.BgXiSpeakBpmSaveDTO;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.modules.tasktask.entity.TaskTask;
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||
@@ -48,12 +54,12 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
@Tag(name="习总书记重要讲话指示批示情况")
|
||||
@RestController
|
||||
@RequestMapping("/bg/xispeak/bgXiSpeak")
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
@Slf4j
|
||||
public class BgXiSpeakController extends JeecgController<BgXiSpeak, IBgXiSpeakService>{
|
||||
@Autowired
|
||||
private IBgXiSpeakService bgXiSpeakService;
|
||||
|
||||
/**
|
||||
private final IBgXiSpeakService bgXiSpeakService;
|
||||
private final RuntimeService runtimeService;
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param bgXiSpeak
|
||||
@@ -66,9 +72,9 @@ public class BgXiSpeakController extends JeecgController<BgXiSpeak, IBgXiSpeakSe
|
||||
@Operation(summary="习总书记重要讲话指示批示情况-分页列表查询")
|
||||
@GetMapping(value = "/rootList")
|
||||
public Result<IPage<BgXiSpeak>> queryPageList(BgXiSpeak bgXiSpeak,
|
||||
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
String hasQuery = req.getParameter("hasQuery");
|
||||
if(hasQuery != null && "true".equals(hasQuery)){
|
||||
QueryWrapper<BgXiSpeak> queryWrapper = QueryGenerator.initQueryWrapper(bgXiSpeak, req.getParameterMap());
|
||||
@@ -223,7 +229,59 @@ public class BgXiSpeakController extends JeecgController<BgXiSpeak, IBgXiSpeakSe
|
||||
bgXiSpeakService.updateBgXiSpeak(bgXiSpeak);
|
||||
return Result.OK("编辑成功!");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存业务数据同时更新流程变量jsonData
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "保存业务数据同时更新流程变量jsonData")
|
||||
@Operation(summary="保存业务数据同时更新流程变量jsonData")
|
||||
@PostMapping(value = "/saveBpmForm")
|
||||
public Result<String> saveBpmForm(@RequestBody BgXiSpeakBpmSaveDTO dto) {
|
||||
if (dto == null || dto.getFormData() == null || oConvertUtils.isEmpty(dto.getFormData().getId())) {
|
||||
return Result.error("表单数据不存在");
|
||||
}
|
||||
if (oConvertUtils.isEmpty(dto.getProcessInstanceId())) {
|
||||
return Result.error("流程实例ID不能为空");
|
||||
}
|
||||
String varField = oConvertUtils.isEmpty(dto.getVarField()) ? "json_data" : dto.getVarField();
|
||||
bgXiSpeakService.updateById(dto.getFormData());
|
||||
Object existingVar = runtimeService.getVariable(dto.getProcessInstanceId(), varField);
|
||||
JSONObject mergedJson = new JSONObject();
|
||||
if (existingVar instanceof String) {
|
||||
try {
|
||||
mergedJson = JSONObject.parseObject((String) existingVar);
|
||||
} catch (Exception e) {
|
||||
log.warn("解析原有流程变量json_data失败,将使用空对象", e);
|
||||
}
|
||||
}
|
||||
if (mergedJson == null) {
|
||||
mergedJson = new JSONObject();
|
||||
}
|
||||
JSONObject formDataJson = (JSONObject) JSON.toJSON(dto.getFormData());
|
||||
if (formDataJson != null) {
|
||||
mergedJson.putAll(formDataJson);
|
||||
}
|
||||
runtimeService.setVariable(dto.getProcessInstanceId(), varField, mergedJson.toJSONString());
|
||||
return Result.OK("保存成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存业务数据同时更新流程变量jsonData
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "根据传入的业务表单id撤回所有在运行的流程")
|
||||
@Operation(summary="根据传入的业务表单id撤回所有在运行的流程")
|
||||
@PostMapping(value = "/withDrawXiSpeak")
|
||||
public Result<String> withDrawXiSpeak(@RequestParam("id") String id) {
|
||||
if(bgXiSpeakService.withDrawXiSpeak(id)){
|
||||
return Result.OK("删除流程成功");
|
||||
}
|
||||
return Result.error("id为" + id + "的xispeak表单删除相关流程失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package org.jeecg.modules.bg.xispeak.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "BgXiSpeak BPM form save DTO")
|
||||
public class BgXiSpeakBpmSaveDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "Process instance id")
|
||||
private String processInstanceId;
|
||||
|
||||
@Schema(description = "Process variable name")
|
||||
private String varField;
|
||||
|
||||
@Schema(description = "BgXiSpeak form data")
|
||||
private BgXiSpeak formData;
|
||||
}
|
||||
+1
@@ -131,6 +131,7 @@ public class BgXiSpeak implements Serializable {
|
||||
/**完成状态(0推进中,1已完成)*/
|
||||
@Excel(name = "完成状态(0推进中,1已完成)", width = 15)
|
||||
@Schema(description = "完成状态(0推进中,1已完成)")
|
||||
@Dict( dicCode = "db_status")
|
||||
private java.lang.Integer completionStatus;
|
||||
/**落实部门id*/
|
||||
@Excel(name = "落实部门id", width = 15, dictTable = "sys_depart", dicText = "depart_name", dicCode = "id")
|
||||
|
||||
+61
-52
@@ -5,71 +5,80 @@ import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: 习总书记重要讲话指示批示情况
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2026-04-16
|
||||
* @Date: 2026-04-16
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface IBgXiSpeakService extends IService<BgXiSpeak> {
|
||||
|
||||
/**根节点父ID的值*/
|
||||
public static final String ROOT_PID_VALUE = "0";
|
||||
|
||||
/**树节点有子节点状态值*/
|
||||
public static final String HASCHILD = "1";
|
||||
|
||||
/**树节点无子节点状态值*/
|
||||
public static final String NOCHILD = "0";
|
||||
/**
|
||||
* 根节点父ID的值
|
||||
*/
|
||||
public static final String ROOT_PID_VALUE = "0";
|
||||
|
||||
/**
|
||||
* 新增节点
|
||||
*
|
||||
* @param bgXiSpeak
|
||||
*/
|
||||
void addBgXiSpeak(BgXiSpeak bgXiSpeak);
|
||||
|
||||
/**
|
||||
* 修改节点
|
||||
*
|
||||
* @param bgXiSpeak
|
||||
* @throws JeecgBootException
|
||||
*/
|
||||
void updateBgXiSpeak(BgXiSpeak bgXiSpeak) throws JeecgBootException;
|
||||
|
||||
/**
|
||||
* 删除节点
|
||||
*
|
||||
* @param id
|
||||
* @throws JeecgBootException
|
||||
*/
|
||||
void deleteBgXiSpeak(String id) throws JeecgBootException;
|
||||
/**
|
||||
* 树节点有子节点状态值
|
||||
*/
|
||||
public static final String HASCHILD = "1";
|
||||
|
||||
/**
|
||||
* 查询所有数据,无分页
|
||||
*
|
||||
* @param queryWrapper
|
||||
* @return List<BgXiSpeak>
|
||||
*/
|
||||
/**
|
||||
* 树节点无子节点状态值
|
||||
*/
|
||||
public static final String NOCHILD = "0";
|
||||
|
||||
/**
|
||||
* 新增节点
|
||||
*
|
||||
* @param bgXiSpeak
|
||||
*/
|
||||
void addBgXiSpeak(BgXiSpeak bgXiSpeak);
|
||||
|
||||
/**
|
||||
* 修改节点
|
||||
*
|
||||
* @param bgXiSpeak
|
||||
* @throws JeecgBootException
|
||||
*/
|
||||
void updateBgXiSpeak(BgXiSpeak bgXiSpeak) throws JeecgBootException;
|
||||
|
||||
/**
|
||||
* 删除节点
|
||||
*
|
||||
* @param id
|
||||
* @throws JeecgBootException
|
||||
*/
|
||||
void deleteBgXiSpeak(String id) throws JeecgBootException;
|
||||
|
||||
/**
|
||||
* 查询所有数据,无分页
|
||||
*
|
||||
* @param queryWrapper
|
||||
* @return List<BgXiSpeak>
|
||||
*/
|
||||
List<BgXiSpeak> queryTreeListNoPage(QueryWrapper<BgXiSpeak> queryWrapper);
|
||||
|
||||
/**
|
||||
* 【vue3专用】根据父级编码加载分类字典的数据
|
||||
*
|
||||
* @param parentCode
|
||||
* @return
|
||||
*/
|
||||
List<SelectTreeModel> queryListByCode(String parentCode);
|
||||
/**
|
||||
* 【vue3专用】根据父级编码加载分类字典的数据
|
||||
*
|
||||
* @param parentCode
|
||||
* @return
|
||||
*/
|
||||
List<SelectTreeModel> queryListByCode(String parentCode);
|
||||
|
||||
/**
|
||||
* 【vue3专用】根据pid查询子节点集合
|
||||
*
|
||||
* @param pid
|
||||
* @return
|
||||
*/
|
||||
List<SelectTreeModel> queryListByPid(String pid);
|
||||
/**
|
||||
* 【vue3专用】根据pid查询子节点集合
|
||||
*
|
||||
* @param pid
|
||||
* @return
|
||||
*/
|
||||
List<SelectTreeModel> queryListByPid(String pid);
|
||||
|
||||
BgXiSpeak getByIdForUpdate(String id);
|
||||
BgXiSpeak getByIdForUpdate(String id);
|
||||
|
||||
boolean withDrawXiSpeak(String id);
|
||||
}
|
||||
|
||||
+58
@@ -1,18 +1,26 @@
|
||||
package org.jeecg.modules.bg.xispeak.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.common.system.vo.SelectTreeModel;
|
||||
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
|
||||
import org.jeecg.modules.bg.xispeak.mapper.BgXiSpeakMapper;
|
||||
import org.jeecg.modules.bg.xispeak.service.IBgXiSpeakService;
|
||||
import org.jeecg.modules.tasktask.entity.TaskTask;
|
||||
import org.jeecg.modules.tasktask.service.impl.TaskTaskServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
|
||||
@@ -23,8 +31,14 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
public class BgXiSpeakServiceImpl extends ServiceImpl<BgXiSpeakMapper, BgXiSpeak> implements IBgXiSpeakService {
|
||||
|
||||
|
||||
private final TaskTaskServiceImpl taskTaskServiceImpl;
|
||||
private final RuntimeService runtimeService;
|
||||
|
||||
@Override
|
||||
public void addBgXiSpeak(BgXiSpeak bgXiSpeak) {
|
||||
//新增时设置hasChild为0
|
||||
@@ -222,4 +236,48 @@ public class BgXiSpeakServiceImpl extends ServiceImpl<BgXiSpeakMapper, BgXiSpeak
|
||||
.eq(BgXiSpeak::getId, id)
|
||||
.last("for update"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean withDrawXiSpeak(String id) {
|
||||
|
||||
// 1. 【查询用】锁住并查询业务数据,带 for update
|
||||
LambdaQueryWrapper<TaskTask> queryWrapper = new LambdaQueryWrapper<TaskTask>()
|
||||
.eq(TaskTask::getBusinessId, id)
|
||||
.last("for update"); // 只有查询才能加这个
|
||||
List<TaskTask> taskTaskList = taskTaskServiceImpl.list(queryWrapper);
|
||||
|
||||
if (taskTaskList == null || taskTaskList.isEmpty()) {
|
||||
log.warn("XiSpeak表单删除流程时 {} 未找到关联的tasktask表单数据", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 提取并去重流程实例 ID
|
||||
List<String> taskTaskProcIdList = taskTaskList.stream()
|
||||
.map(TaskTask::getProcessInstId)
|
||||
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
|
||||
// 3. 循环处理流程引擎中的数据
|
||||
for (String procId : taskTaskProcIdList) {
|
||||
long count = runtimeService.createProcessInstanceQuery()
|
||||
.processInstanceId(procId)
|
||||
.count();
|
||||
|
||||
if (count > 0) {
|
||||
String delReason = "删除xispeak表单关联的tasktask表单中流程id为" + procId + "的流程";
|
||||
runtimeService.deleteProcessInstance(procId, delReason);
|
||||
log.info("成功中止运行中的流程实例: {}", procId);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 【核心修改:删除用】重新创建一个干净的 Wrapper,绝不能带 for update!
|
||||
LambdaQueryWrapper<TaskTask> deleteWrapper = new LambdaQueryWrapper<TaskTask>()
|
||||
.eq(TaskTask::getBusinessId, id); // 不要加 .last("for update")
|
||||
|
||||
taskTaskServiceImpl.remove(deleteWrapper); // 使用干净的 Wrapper 执行删除
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -43,6 +43,14 @@ public class TaskTaskServiceImpl extends ServiceImpl<TaskTaskMapper, TaskTask> i
|
||||
newTask.setStartTime(null);
|
||||
this.save(newTask);
|
||||
Result<String> res = bpmBaseExtApiImpl.startMutilProcess(taskTask.getFlowCode(), newTask.getId(), taskTask.getFormUrl(), taskTask.getFormUrl(), userName, jsonString);
|
||||
String procId = res.getResult();
|
||||
if(StringUtils.isBlank(procId)){
|
||||
log.warn("流程启动失败");
|
||||
return false;
|
||||
}else{
|
||||
newTask.setProcessInstId(procId);
|
||||
}
|
||||
this.updateById(newTask);
|
||||
return res.isSuccess();
|
||||
}
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
||||
Reference in New Issue
Block a user