feat: 提交流程中心后端代码
build / build-push (push) Successful in 28s

Spring Boot 流程引擎服务:流程定义/实例/任务、审批人解析、
回调分发、oapi 接口及单元测试。
保留远程 .gitea/workflows/build.yml 与 docker/Dockerfile,
新增 .gitignore 排除 target/ 构建产物。
This commit is contained in:
chenxing
2026-09-15 10:42:56 +08:00
parent 0296b2b5dd
commit c1103aeb29
65 changed files with 7119 additions and 0 deletions
@@ -0,0 +1,62 @@
package com.yunhai.flowcenter.engine;
import com.yunhai.flowcenter.entity.FlwDef;
import com.yunhai.flowcenter.entity.FlwInstance;
import com.yunhai.flowcenter.enums.FlwEnums;
import com.yunhai.flowcenter.repository.FlwDefRepository;
import com.yunhai.flowcenter.repository.FlwInstanceRepository;
import com.yunhai.flowcenter.repository.FlwTaskRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* 节点放行推进(AFTER_COMMIT 监听器经代理调用本 bean,REQUIRES_NEW 生效——
* 事务已提交后的同步监听阶段没有活动事务,@Modifying 批量语句必须有新事务承载):
* 该节点待办清零且办件在途才推进;并发冲突由 flw_instance.version 乐观锁暴露,监听器层负责重试。
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class FlowAdvanceService {
private final FlwInstanceRepository instanceRepository;
private final FlwDefRepository defRepository;
private final FlwTaskRepository taskRepository;
private final FlowEngine flowEngine;
/** @return 是否实际推进了 */
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean tryAdvance(Long instanceId, String nodeId) {
FlwInstance instance = instanceRepository.findById(instanceId).orElse(null);
if (instance == null
|| instance.getStatus() != FlwEnums.InstanceStatus.APPROVING.getCode()) {
return false;
}
// 已推进过的节点不再放行(currentNodes 由引擎在放行时移除,乐观锁保证互斥)
String current = instance.getCurrentNodes();
boolean active = current != null && java.util.Arrays.stream(current.split(","))
.anyMatch(nodeId::equals);
if (!active) {
return false;
}
long pending = taskRepository.findByInstanceIdAndStatus(instanceId,
FlwEnums.TaskStatus.PENDING.getCode()).stream()
.filter(t -> nodeId.equals(t.getNodeId()))
.count();
if (pending > 0) {
return false;
}
FlwDef def = defRepository.findById(instance.getDefId()).orElse(null);
if (def == null) {
log.error("[flow-center] 办件定义缺失,推进中止:instance={} defId={}",
instanceId, instance.getDefId());
return false;
}
flowEngine.continueAdvance(instance, def, nodeId);
instanceRepository.save(instance);
return true;
}
}