Compare commits

..

No commits in common. '038b52c64d1ff53ca8580e34c99988bc630bef36' and '845af296ec673897a630da7c599a1d4c08c1b9be' have entirely different histories.

  1. 99
      common/common-botp/src/main/java/apelet/common/botp/model/constant/SplitMergeStrategyEnum.java
  2. 105
      common/common-botp/src/main/java/apelet/common/botp/model/constant/ValueMethodEnum.java
  3. 107
      common/common-botp/src/main/java/apelet/common/botp/service/impl/ConvertRuleServiceImpl.java
  4. 39
      common/common-flow/src/main/java/apelet/common/flow/controller/FlowOperationController.java
  5. 6
      common/common-flow/src/main/java/apelet/common/flow/service/FlowApiService.java
  6. 10
      common/common-flow/src/main/java/apelet/common/flow/service/FlowEntryService.java
  7. 11
      common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowApiServiceImpl.java
  8. 11
      common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowEntryServiceImpl.java
  9. 21
      common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowTaskTitleBackfillServiceImpl.java
  10. 2
      common/pom.xml
  11. 4
      pom.xml

99
common/common-botp/src/main/java/apelet/common/botp/model/constant/SplitMergeStrategyEnum.java

@ -1,99 +0,0 @@ @@ -1,99 +0,0 @@
package apelet.common.botp.model.constant;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 分单/合并策略枚举。
*
* <p>对应 convert_rule.split_merge_strategy,落库为 varchar 的 "1"/"2"/"3",默认按「一对一」处理。</p>
*
* @author admin
* @since 2024-01-18
*/
public enum SplitMergeStrategyEnum {
/**
* 一对一:一条源单对应一条目标单。
*/
ONE_TO_ONE("1", "一对一"),
/**
* 多对一:多条源单合并为一条目标单。
*/
MANY_TO_ONE("2", "多对一"),
/**
* 按规则分组合并:按分单字段分组后分别合并。
*/
GROUP_BY_RULE("3", "按规则分组合并");
@Getter
private final String code;
@Getter
private final String description;
private static final Map<String, SplitMergeStrategyEnum> ENUM_MAP;
SplitMergeStrategyEnum(String code, String description) {
this.code = code;
this.description = description;
}
static {
ENUM_MAP = Arrays.stream(values()).collect(Collectors.toMap(SplitMergeStrategyEnum::getCode, e -> e));
}
/**
* 根据 code 获取枚举对象。
*
* @param code 分单策略编码。
* @return 枚举对象。
*/
public static SplitMergeStrategyEnum of(String code) {
return Optional.ofNullable(ENUM_MAP.get(code))
.orElseThrow(() -> new IllegalArgumentException("无法根据 code 获取分单策略:" + code));
}
/**
* 根据 code 获取枚举对象,空值按「一对一」处理(与字段默认值一致)。
*
* @param code 分单策略编码。
* @return 枚举对象。
*/
public static SplitMergeStrategyEnum ofNullable(String code) {
if (StringUtils.isBlank(code)) {
return ONE_TO_ONE;
}
return of(code.trim());
}
/**
* 根据 code 获取枚举对象,空值或未知 code 均返回 null(不兜底、不抛异常)。
*
* <p>供保存校验等场景使用:需要区分「未配置」与「配置了非法值」时,用本方法。</p>
*
* @param code 分单策略编码。
* @return 枚举对象;不是已知编码时返回 null。
*/
public static SplitMergeStrategyEnum parse(String code) {
return StringUtils.isBlank(code) ? null : ENUM_MAP.get(code.trim());
}
/**
* 生成可选值说明,用于错误提示。
*
* @return 形如「1-一对一 2-多对一 3-按规则分组合并」。
*/
public static String validOptions() {
return Arrays.stream(values())
.map(e -> e.getCode() + "-" + e.getDescription())
.collect(Collectors.joining(" "));
}
}

105
common/common-botp/src/main/java/apelet/common/botp/model/constant/ValueMethodEnum.java

@ -1,105 +0,0 @@ @@ -1,105 +0,0 @@
package apelet.common.botp.model.constant;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 字段取值方式枚举。
*
* <p>对应 convert_fieldmapping_entry.value_method,落库为 varchar 的 "1"/"2"/"3"/"4"。</p>
*
* @author admin
* @since 2024-01-18
*/
public enum ValueMethodEnum {
/**
* 映射:取源单同名字段的值。
*/
MAPPING("1", "映射"),
/**
* 常量:直接使用配置的固定值。
*/
CONSTANT("2", "常量"),
/**
* 计算公式:按配置的公式表达式计算。
*/
EXPRESSION("3", "计算公式"),
/**
* 按条件取值
*/
CONDITION("4", "按条件取值")
;
@Getter
private final String code;
@Getter
private final String description;
private static final Map<String, ValueMethodEnum> ENUM_MAP;
ValueMethodEnum(String code, String description) {
this.code = code;
this.description = description;
}
static {
ENUM_MAP = Arrays.stream(values()).collect(Collectors.toMap(ValueMethodEnum::getCode, e -> e));
}
/**
* 根据 code 获取枚举对象。
*
* @param code 取值方式编码。
* @return 枚举对象。
*/
public static ValueMethodEnum of(String code) {
return Optional.ofNullable(ENUM_MAP.get(code))
.orElseThrow(() -> new IllegalArgumentException("无法根据 code 获取字段取值方式:" + code));
}
/**
* 根据 code 获取枚举对象,空值按「映射」处理(与字段默认值一致)。
*
* @param code 取值方式编码。
* @return 枚举对象。
*/
public static ValueMethodEnum ofNullable(String code) {
if (StringUtils.isBlank(code)) {
return MAPPING;
}
return of(code.trim());
}
/**
* 根据 code 获取枚举对象,空值或未知 code 均返回 null(不兜底、不抛异常)。
*
* <p>供保存校验等场景使用:需要区分「未配置」与「配置了非法值」时,用本方法。</p>
*
* @param code 取值方式编码。
* @return 枚举对象;不是已知编码时返回 null。
*/
public static ValueMethodEnum parse(String code) {
return StringUtils.isBlank(code) ? null : ENUM_MAP.get(code.trim());
}
/**
* 生成可选值说明,用于错误提示。
*
* @return 形如「1-映射 2-常量 3-计算公式 4-按条件取值」。
*/
public static String validOptions() {
return Arrays.stream(values())
.map(e -> e.getCode() + "-" + e.getDescription())
.collect(Collectors.joining(" "));
}
}

107
common/common-botp/src/main/java/apelet/common/botp/service/impl/ConvertRuleServiceImpl.java

@ -5,8 +5,6 @@ import apelet.common.botp.dao.ConvertPluginEntryMapper; @@ -5,8 +5,6 @@ import apelet.common.botp.dao.ConvertPluginEntryMapper;
import apelet.common.botp.dao.ConvertRuleMapper;
import apelet.common.botp.dto.*;
import apelet.common.botp.model.*;
import apelet.common.botp.model.constant.SplitMergeStrategyEnum;
import apelet.common.botp.model.constant.ValueMethodEnum;
import apelet.common.botp.service.*;
import apelet.common.botp.service.execute.BotpService;
import apelet.common.botp.service.execute.entity.BillData;
@ -15,7 +13,6 @@ import apelet.common.botp.util.Constant; @@ -15,7 +13,6 @@ import apelet.common.botp.util.Constant;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.constant.GlobalDeletedFlag;
import apelet.common.core.exception.MyRuntimeException;
import apelet.common.core.object.*;
import apelet.common.generator.dao.OnlFormHeadMapper;
import apelet.common.generator.model.OnlFormField;
@ -34,7 +31,6 @@ import org.jetbrains.annotations.NotNull; @@ -34,7 +31,6 @@ import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
@ -103,14 +99,11 @@ public class ConvertRuleServiceImpl extends BaseService<ConvertRule,Long> implem @@ -103,14 +99,11 @@ public class ConvertRuleServiceImpl extends BaseService<ConvertRule,Long> implem
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean editAll(ConvertRule convertRule) {
Long id = convertRule.getId();
if (null==id){
return false;
}
//保存前校验(分单策略、字段映射取值方式),不通过直接阻止保存
validateBeforeSave(convertRule);
//设置主数据基本信息
addOrUpdateBaseData(convertRule,null);
boolean update = this.updateById(convertRule);
@ -121,10 +114,7 @@ public class ConvertRuleServiceImpl extends BaseService<ConvertRule,Long> implem @@ -121,10 +114,7 @@ public class ConvertRuleServiceImpl extends BaseService<ConvertRule,Long> implem
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean addAll(ConvertRule convertRule) {
//保存前校验(分单策略、字段映射取值方式),不通过直接阻止保存
validateBeforeSave(convertRule);
//设置主数据基本信息
addOrUpdateBaseData(convertRule,null);
boolean save = this.save(convertRule);
@ -136,100 +126,6 @@ public class ConvertRuleServiceImpl extends BaseService<ConvertRule,Long> implem @@ -136,100 +126,6 @@ public class ConvertRuleServiceImpl extends BaseService<ConvertRule,Long> implem
return addChild(convertRule,id);
}
/**
* 保存前的规则级校验。
*
* <p>集中校验转换规则本身与其字段映射分录,任一不通过即抛出 {@link MyRuntimeException} 阻止保存。</p>
*
* @param convertRule 待保存的转换规则。
*/
private void validateBeforeSave(ConvertRule convertRule) {
validateSplitMergeStrategy(convertRule);
validateFieldmappingValueMethod(convertRule);
}
/**
* 校验分单策略配置。
*
* <p>分单策略为空时按「一对一」处理(与字段默认值一致);配置了非法值时阻止保存;
* 选择「按规则分组合并」时必须配置分单字段。</p>
*
* @param convertRule 待保存的转换规则。
*/
private void validateSplitMergeStrategy(ConvertRule convertRule) {
String splitMergeStrategy = convertRule.getSplitMergeStrategy();
if (StringUtils.isBlank(splitMergeStrategy)) {
// 未配置按默认值「一对一」处理,与 SplitMergeStrategyEnum.ofNullable 保持一致
return;
}
SplitMergeStrategyEnum strategy = SplitMergeStrategyEnum.parse(splitMergeStrategy);
if (strategy == null) {
throw new MyRuntimeException("分单策略未知:" + splitMergeStrategy
+ ",可选值为 " + SplitMergeStrategyEnum.validOptions());
}
if (strategy == SplitMergeStrategyEnum.GROUP_BY_RULE
&& StringUtils.isBlank(convertRule.getGroupByField())) {
throw new MyRuntimeException("分单策略为「" + SplitMergeStrategyEnum.GROUP_BY_RULE.getDescription()
+ "」时必须配置分单字段,可选值为 " + SplitMergeStrategyEnum.validOptions());
}
}
/**
* 校验字段映射分录的取值方式。
*
* <p>取值方式为空或不在 {@link ValueMethodEnum} 允许范围内时,直接抛出异常阻止保存,
* 并在异常信息中定位到具体的分录行(第几行、源字段、目标字段),便于前端定位问题。</p>
*
* @param convertRule 待保存的转换规则,含字段映射分录。
*/
private void validateFieldmappingValueMethod(ConvertRule convertRule) {
List<ConvertFieldmappingEntry> fieldmappingEntries = convertRule.getConvertFieldmappingEntry();
if (ObjectUtil.isEmpty(fieldmappingEntries)) {
return;
}
for (int i = 0; i < fieldmappingEntries.size(); i++) {
ConvertFieldmappingEntry entry = fieldmappingEntries.get(i);
if (entry == null) {
continue;
}
String valueMethod = entry.getValueMethod();
if (StringUtils.isBlank(valueMethod)) {
throw new MyRuntimeException(buildValueMethodErrorMsg(i, entry, "未配置取值方式"));
}
if (ValueMethodEnum.parse(valueMethod) == null) {
throw new MyRuntimeException(buildValueMethodErrorMsg(i, entry, "取值方式未知:" + valueMethod));
}
}
}
/**
* 构建取值方式校验失败的定位信息。
*
* @param index 分录行下标(从 0 开始)。
* @param entry 出错的分录。
* @param reason 具体原因。
* @return 带行号与字段定位的错误信息。
*/
private String buildValueMethodErrorMsg(int index, ConvertFieldmappingEntry entry, String reason) {
StringBuilder msg = new StringBuilder("字段映射第 ").append(index + 1).append(" 行");
if (StringUtils.isNotBlank(entry.getOldfieldName()) || StringUtils.isNotBlank(entry.getOldfieldNumber())) {
msg.append("(源字段:")
.append(StringUtils.defaultIfBlank(entry.getOldfieldName(), entry.getOldfieldNumber()))
.append(")");
}
if (StringUtils.isNotBlank(entry.getNewfieldName()) || StringUtils.isNotBlank(entry.getNewfieldNumber())) {
msg.append("(目标字段:")
.append(StringUtils.defaultIfBlank(entry.getNewfieldName(), entry.getNewfieldNumber()))
.append(")");
}
msg.append(" ").append(reason)
.append(",可选值为 ").append(ValueMethodEnum.validOptions());
if (entry.getId() != null) {
msg.append(",分录id=").append(entry.getId());
}
return msg.toString();
}
@Override
public List<ConvertRule> getConvertRuleListWithRelation(ConvertRule convertRuleFilter, String buildOrderBy) {
LambdaQueryWrapper<ConvertRule> queryWrapper = new LambdaQueryWrapper<>(convertRuleFilter);
@ -302,8 +198,7 @@ public class ConvertRuleServiceImpl extends BaseService<ConvertRule,Long> implem @@ -302,8 +198,7 @@ public class ConvertRuleServiceImpl extends BaseService<ConvertRule,Long> implem
}
@Transactional(rollbackFor = Exception.class)
public void removeChild(Long id){
private void removeChild(Long id){
convertPluginEntryService.remove(new LambdaQueryWrapper<ConvertPluginEntry>().eq(ConvertPluginEntry::getParentId,id));
convertFieldmappingEntryService.remove(new LambdaQueryWrapper<ConvertFieldmappingEntry>().eq(ConvertFieldmappingEntry::getParentId,id));
}

39
common/common-flow/src/main/java/apelet/common/flow/controller/FlowOperationController.java

@ -219,12 +219,13 @@ public class FlowOperationController { @@ -219,12 +219,13 @@ public class FlowOperationController {
if (StrUtil.isNotBlank(flowTaskExt.getVariableListJson())) {
taskInfoVo.setVariableList(JSON.parseArray(flowTaskExt.getVariableListJson(), JSONObject.class));
}
FlowWorkOrder workOrder = flowWorkOrderService.getFlowWorkOrderByProcessInstanceId(processInstanceId);
// 单条详情:只查一次节点扩展(复用批量接口传单元素集合),无 N+1 风险。
String taskKey = taskInfoVo.getTaskKey();
FlowTaskInstanceExt taskInstanceExt = StrUtil.isBlank(taskKey) ? null
FlowTaskInstanceExt taskInstanceExt = workOrder == null || StrUtil.isBlank(taskKey) ? null
: flowTaskInstanceExtService.getMapByProcessInstanceIds(CollUtil.newHashSet(processInstanceId))
.get(processInstanceId + ":" + taskKey);
taskInfoVo.setTitle(flowApiService.resolveTitleCached(taskInstanceExt));
taskInfoVo.setTitle(flowApiService.resolveTitleCached(workOrder, taskKey, taskInstanceExt));
}
return ResponseResult.success(taskInfoVo);
}
@ -834,16 +835,24 @@ public class FlowOperationController { @@ -834,16 +835,24 @@ public class FlowOperationController {
pageData.getDataList().forEach(instance -> resultList.add(BeanUtil.beanToMap(instance)));
List<HistoricTaskInstance> taskInstanceList = pageData.getDataList();
if (CollUtil.isNotEmpty(taskInstanceList)) {
Set<String> instanceIdSet = taskInstanceList.stream().map(HistoricTaskInstance::getProcessInstanceId).collect(Collectors.toSet());
Set<String> instanceIdSet = taskInstanceList.stream()
.map(HistoricTaskInstance::getProcessInstanceId).collect(Collectors.toSet());
List<HistoricProcessInstance> instanceList = flowApiService.getHistoricProcessInstanceList(instanceIdSet);
Set<String> loginNameSet = instanceList.stream().map(HistoricProcessInstance::getStartUserId).collect(Collectors.toSet());
List<FlowUserInfoVo> userInfoList = flowCustomExtFactory.getFlowIdentityExtHelper().getUserInfoListByUsernameSet(loginNameSet);
Map<String, FlowUserInfoVo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(FlowUserInfoVo::getLoginName, c -> c));
Map<String, HistoricProcessInstance> instanceMap = instanceList.stream().collect(Collectors.toMap(HistoricProcessInstance::getId, c -> c));
List<FlowWorkOrder> workOrderList = flowWorkOrderService.getInList(INSTANCE_ID, instanceIdSet);
Map<String, FlowWorkOrder> workOrderMap = workOrderList.stream().collect(Collectors.toMap(FlowWorkOrder::getProcessInstanceId, c -> c));
Set<String> loginNameSet = instanceList.stream()
.map(HistoricProcessInstance::getStartUserId).collect(Collectors.toSet());
List<FlowUserInfoVo> userInfoList = flowCustomExtFactory
.getFlowIdentityExtHelper().getUserInfoListByUsernameSet(loginNameSet);
Map<String, FlowUserInfoVo> userInfoMap =
userInfoList.stream().collect(Collectors.toMap(FlowUserInfoVo::getLoginName, c -> c));
Map<String, HistoricProcessInstance> instanceMap =
instanceList.stream().collect(Collectors.toMap(HistoricProcessInstance::getId, c -> c));
List<FlowWorkOrder> workOrderList =
flowWorkOrderService.getInList(INSTANCE_ID, instanceIdSet);
Map<String, FlowWorkOrder> workOrderMap =
workOrderList.stream().collect(Collectors.toMap(FlowWorkOrder::getProcessInstanceId, c -> c));
// 节点标题按实例批量预载(一次 IN 查询覆盖整页),避免逐行查询造成 N+1。
Map<String, FlowTaskInstanceExt> taskInstanceExtMap = flowTaskInstanceExtService.getMapByProcessInstanceIds(instanceIdSet);
Map<String, FlowTaskInstanceExt> taskInstanceExtMap =
flowTaskInstanceExtService.getMapByProcessInstanceIds(instanceIdSet);
resultList.forEach(result -> {
String instanceId = result.get(INSTANCE_ID).toString();
HistoricProcessInstance instance = instanceMap.get(instanceId);
@ -860,13 +869,15 @@ public class FlowOperationController { @@ -860,13 +869,15 @@ public class FlowOperationController {
// 标题只认 zz_flow_task_instance_ext 的落库值:没有标题行就是空
Object taskDefinitionKey = result.get("taskDefinitionKey");
String taskKey = taskDefinitionKey == null ? null : taskDefinitionKey.toString();
result.put("title", flowApiService.resolveTitleCached(
result.put("title", flowApiService.resolveTitleCached(flowWorkOrder, taskKey,
taskKey == null ? null : taskInstanceExtMap.get(instanceId + ":" + taskKey)));
}
});
Set<String> taskIdSet = taskInstanceList.stream().map(HistoricTaskInstance::getId).collect(Collectors.toSet());
Set<String> taskIdSet =
taskInstanceList.stream().map(HistoricTaskInstance::getId).collect(Collectors.toSet());
List<FlowTaskComment> commentList = flowTaskCommentService.getFlowTaskCommentListByTaskIds(taskIdSet);
Map<String, List<FlowTaskComment>> commentMap = commentList.stream().collect(Collectors.groupingBy(FlowTaskComment::getTaskId));
Map<String, List<FlowTaskComment>> commentMap =
commentList.stream().collect(Collectors.groupingBy(FlowTaskComment::getTaskId));
resultList.forEach(result -> {
List<FlowTaskComment> comments = commentMap.get(result.get("id").toString());
if (CollUtil.isNotEmpty(comments)) {
@ -945,7 +956,7 @@ public class FlowOperationController { @@ -945,7 +956,7 @@ public class FlowOperationController {
data.put("flowStatus", workOrder.getFlowStatus());
// 流程实例列表使用起始节点的标题;标题只认落库值,没有标题行就是空
String initTaskKey = initTaskKeyMap.get(instance.getProcessDefinitionId());
data.put("title", flowApiService.resolveTitleCached(
data.put("title", flowApiService.resolveTitleCached(workOrder, initTaskKey,
initTaskKey == null ? null : taskInstanceExtMap.get(instance.getId() + ":" + initTaskKey)));
}
resultList.add(data);

6
common/common-flow/src/main/java/apelet/common/flow/service/FlowApiService.java

@ -671,10 +671,12 @@ public interface FlowApiService { @@ -671,10 +671,12 @@ public interface FlowApiService {
* 本方法只读落库值,<b>不做实时解析兜底</b>:没有标题行就返回 null,列表上该行标题为空。
* 因此存量数据(改造前已跑的实例)标题会为空,需要回填后才有。</p>
*
* @param taskInstanceExt 节点扩展对象(调用方按 (实例, 节点) 批量预载,避免逐行查询),可为空。
* @param workOrder 流程工单对象,为空时返回 null。
* @param taskKey BPMN 节点Id,用于定位标题行,为空时返回 null。
* @param taskInstanceExt 节点扩展对象(调用方批量预载,避免逐行查询),可为空。
* @return 落库的标题;没有标题行返回 null。
*/
String resolveTitleCached(FlowTaskInstanceExt taskInstanceExt);
String resolveTitleCached(FlowWorkOrder workOrder, String taskKey, FlowTaskInstanceExt taskInstanceExt);
/**
* 生成指定节点的标题并落库到 zz_flow_task_instance_ext。

10
common/common-flow/src/main/java/apelet/common/flow/service/FlowEntryService.java

@ -79,16 +79,6 @@ public interface FlowEntryService extends IBaseService<FlowEntry, Long> { @@ -79,16 +79,6 @@ public interface FlowEntryService extends IBaseService<FlowEntry, Long> {
*/
FlowEntry getFlowEntryFromCache(String processDefinitionKey);
/**
* 根据流程定义标识获取流程对象。从缓存中读取,如不存在则从数据库读取后,再同步到缓存。
*
* @param processDefinitionKey 流程定义标识。
* @param isToken 是否存在登录态
* @return 流程对象。
*/
FlowEntry getFlowEntryFromCache(String processDefinitionKey ,Boolean isToken);
/**
* 根据流程Id获取流程发布列表数据。
*

11
common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowApiServiceImpl.java

@ -1024,7 +1024,7 @@ public class FlowApiServiceImpl implements FlowApiService { @@ -1024,7 +1024,7 @@ public class FlowApiServiceImpl implements FlowApiService {
}
// 标题只以 zz_flow_task_instance_ext 的落库值为准:没有标题行就是空,
// 不需要再按"节点配没配模板""是不是在线表单"做前置判断(那两个条件对标题行本身没有约束力)。
flowTaskVo.setTitle(this.resolveTitleCached(
flowTaskVo.setTitle(this.resolveTitleCached(flowWorkOrder, task.getTaskDefinitionKey(),
taskInstanceExtMap.get(task.getProcessInstanceId() + ":" + task.getTaskDefinitionKey())));
flowTaskVoList.add(flowTaskVo);
}
@ -2962,11 +2962,14 @@ public class FlowApiServiceImpl implements FlowApiService { @@ -2962,11 +2962,14 @@ public class FlowApiServiceImpl implements FlowApiService {
}
@Override
public String resolveTitleCached(FlowTaskInstanceExt taskInstanceExt) {
public String resolveTitleCached(FlowWorkOrder workOrder, String taskKey, FlowTaskInstanceExt taskInstanceExt) {
// 标题只以 zz_flow_task_instance_ext 的落库值为准,不再回退到按模板实时解析。
// 这样"这个节点到底有没有落库"在列表上一眼可见,排查/联调时不会被实时兜底掩盖。
String title = taskInstanceExt == null ? null : taskInstanceExt.getTitle();
return StrUtil.isBlank(title) ? null : title;
if (workOrder == null || taskInstanceExt == null || StrUtil.isBlank(taskKey)
|| StrUtil.isBlank(taskInstanceExt.getTitle())) {
return null;
}
return taskInstanceExt.getTitle();
}
@Override

11
common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowEntryServiceImpl.java

@ -240,21 +240,10 @@ public class FlowEntryServiceImpl extends BaseService<FlowEntry, Long> implement @@ -240,21 +240,10 @@ public class FlowEntryServiceImpl extends BaseService<FlowEntry, Long> implement
@Override
public FlowEntry getFlowEntryFromCache(String processDefinitionKey) {
return getFlowEntryFromCache(processDefinitionKey, true);
}
@Override
public FlowEntry getFlowEntryFromCache(String processDefinitionKey, Boolean isToken) {
String key = FlowRedisKeyUtil.makeFlowEntryKey(processDefinitionKey);
LambdaQueryWrapper<FlowEntry> qw = new LambdaQueryWrapper<>();
qw.eq(FlowEntry::getProcessDefinitionKey, processDefinitionKey);
if (Boolean.FALSE.equals(isToken)) {
return commonRedisUtil.getFromCacheWithQueryWrapper(key, qw, flowEntryMapper::selectOne, FlowEntry.class);
}
TokenData tokenData = TokenData.takeFromRequest();
if (tokenData == null) {
return null;
}
if (StrUtil.isNotBlank(tokenData.getAppCode())) {
qw.eq(FlowEntry::getAppCode, tokenData.getAppCode());
} else {

21
common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowTaskTitleBackfillServiceImpl.java

@ -11,7 +11,12 @@ import apelet.common.flow.model.FlowTaskExt; @@ -11,7 +11,12 @@ import apelet.common.flow.model.FlowTaskExt;
import apelet.common.flow.model.FlowTaskInstanceExt;
import apelet.common.flow.model.FlowWorkOrder;
import apelet.common.flow.model.constant.FlowBindFormType;
import apelet.common.flow.service.*;
import apelet.common.flow.service.FlowApiService;
import apelet.common.flow.service.FlowEntryService;
import apelet.common.flow.service.FlowTaskExtService;
import apelet.common.flow.service.FlowTaskInstanceExtService;
import apelet.common.flow.service.FlowTaskTitleBackfillService;
import apelet.common.flow.service.FlowWorkOrderService;
import apelet.common.flow.vo.FlowTaskTitleBackfillVo;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
@ -25,7 +30,11 @@ import org.flowable.task.api.history.HistoricTaskInstance; @@ -25,7 +30,11 @@ import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 节点标题回填服务实现。
@ -75,7 +84,7 @@ public class FlowTaskTitleBackfillServiceImpl implements FlowTaskTitleBackfillSe @@ -75,7 +84,7 @@ public class FlowTaskTitleBackfillServiceImpl implements FlowTaskTitleBackfillSe
result.setDryRun(onlyCount);
// 回填是没有登录态的运维动作,且要跨租户跑;关掉数据权限过滤,
// 否则 getMasterData -> buildDataPermFilter -> processDataPerm 会因 TokenData 为空而 NPE。
boolean dataFilterEnabled = false;
boolean dataFilterEnabled = GlobalThreadLocal.setDataFilter(false);
try {
List<FlowWorkOrder> workOrderList = flowWorkOrderService.getListByWorkOrderIdAfter(cursorWorkOrderId, size);
for (FlowWorkOrder workOrder : workOrderList) {
@ -104,10 +113,8 @@ public class FlowTaskTitleBackfillServiceImpl implements FlowTaskTitleBackfillSe @@ -104,10 +113,8 @@ public class FlowTaskTitleBackfillServiceImpl implements FlowTaskTitleBackfillSe
if (StrUtil.isBlank(processInstanceId)) {
return;
}
if (StrUtil.isBlank(workOrder.getProcessDefinitionKey())) {
return;
}
FlowEntry flowEntry = flowEntryService.getFlowEntryFromCache(workOrder.getProcessDefinitionKey(), false);
FlowEntry flowEntry = StrUtil.isBlank(workOrder.getProcessDefinitionKey()) ? null
: flowEntryService.getFlowEntryFromCache(workOrder.getProcessDefinitionKey());
// 路由表单流程本来就没有标题,跳过
if (flowEntry == null || !ObjectUtil.equal(flowEntry.getBindFormType(), FlowBindFormType.ONLINE_FORM)) {
return;

2
common/pom.xml

@ -25,8 +25,6 @@ @@ -25,8 +25,6 @@
<module>common-openapi</module>
<module>common-core</module>
<module>common-botp</module>
</modules>

4
pom.xml

@ -138,13 +138,13 @@ @@ -138,13 +138,13 @@
<repository>
<id>nexus</id>
<name>nexus</name>
<url>http://192.168.100.25:8081/repository/maven-releases/</url>
<url>http://58.48.135.45:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>maven-snapshots</id>
<name>maven-snapshots</name>
<url>http://192.168.100.25:8081/repository/maven-snapshots/</url>
<url>http://58.48.135.45:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>

Loading…
Cancel
Save