diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeDefinitionConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeDefinitionConverter.java deleted file mode 100644 index fe9561c2..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeDefinitionConverter.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter; - -import com.qqchen.deploy.backend.framework.converter.BaseConverter; -import com.qqchen.deploy.backend.workflow.dto.NodeDefinitionDTO; -import com.qqchen.deploy.backend.workflow.entity.NodeDefinition; -import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Named; - -/** - * 节点定义转换器 - */ -@Mapper(config = BaseConverter.class) -public interface NodeDefinitionConverter extends BaseConverter { - - @Override - @Mapping(target = "workflowDefinitionId", source = "workflowDefinition", qualifiedByName = "getWorkflowDefinitionId") - NodeDefinitionDTO toDto(NodeDefinition entity); - - @Override - @Mapping(target = "workflowDefinition", source = "workflowDefinitionId", qualifiedByName = "createWorkflowDefinition") - NodeDefinition toEntity(NodeDefinitionDTO dto); - - @Named("getWorkflowDefinitionId") - default Long getWorkflowDefinitionId(WorkflowDefinition workflowDefinition) { - return workflowDefinition != null ? workflowDefinition.getId() : null; - } - - @Named("createWorkflowDefinition") - default WorkflowDefinition createWorkflowDefinition(Long id) { - if (id == null) { - return null; - } - WorkflowDefinition workflowDefinition = new WorkflowDefinition(); - workflowDefinition.setId(id); - return workflowDefinition; - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeDefinition.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeDefinition.java deleted file mode 100644 index cde44ce8..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeDefinition.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto; - -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.Data; - -import java.util.List; -import java.util.Map; - -/** - * 节点定义DTO,用于解析工作流定义中的节点配置 - */ -@Data -public class NodeDefinition { - /** - * 节点ID - */ - private String id; - - /** - * 节点类型 - */ - private NodeTypeEnum type; - - /** - * 节点名称 - */ - private String name; - - /** - * 下一个节点的ID列表 - */ - private List next; - - /** - * 节点配置,不同类型的节点有不同的配置 - */ - private Map config; -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowNodeException.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowNodeException.java new file mode 100644 index 00000000..4fa928e0 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowNodeException.java @@ -0,0 +1,28 @@ +package com.qqchen.deploy.backend.workflow.engine.exception; + +import com.qqchen.deploy.backend.framework.enums.ResponseCode; +import com.qqchen.deploy.backend.framework.exception.BusinessException; +import lombok.Getter; + +/** + * 工作流节点相关异常 + */ +@Getter +public class WorkflowNodeException extends BusinessException { + + private final String nodeId; + private final String nodeName; + + public WorkflowNodeException(ResponseCode code, String nodeId, String nodeName) { + super(code, new Object[]{nodeId, nodeName}); + this.nodeId = nodeId; + this.nodeName = nodeName; + } + + public WorkflowNodeException(ResponseCode code, String nodeId, String nodeName, Throwable cause) { + super(code, new Object[]{nodeId, nodeName, cause.getMessage()}); + this.nodeId = nodeId; + this.nodeName = nodeName; + } + +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/transition/TransitionExecutor.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/transition/TransitionExecutor.java index 67c802c1..c634d890 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/transition/TransitionExecutor.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/transition/TransitionExecutor.java @@ -1,14 +1,8 @@ package com.qqchen.deploy.backend.workflow.engine.transition; -import com.qqchen.deploy.backend.system.enums.LogLevelEnum; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.entity.NodeDefinition; import com.qqchen.deploy.backend.workflow.entity.NodeInstance; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; -import com.qqchen.deploy.backend.workflow.repository.INodeDefinitionRepository; import com.qqchen.deploy.backend.workflow.repository.INodeInstanceRepository; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -24,9 +18,6 @@ public class TransitionExecutor { @Resource private TransitionRuleEngine transitionRuleEngine; - @Resource - private INodeDefinitionRepository nodeDefinitionRepository; - @Resource private INodeInstanceRepository nodeInstanceRepository; @@ -37,27 +28,6 @@ public class TransitionExecutor { // 1. 获取下一个节点ID列表 List nextNodeIds = transitionRuleEngine.getNextNodeIds(currentNode, definition, context); - // 2. 创建下一个节点实例 - for (String nodeId : nextNodeIds) { - NodeDefinition nextNodeDef = nodeDefinitionRepository.findByWorkflowDefinitionIdAndNodeIdAndDeletedFalse( - definition.getId(), nodeId); - if (nextNodeDef == null) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_NOT_FOUND, "未找到节点定义: " + nodeId); - } - - NodeInstance nextNode = new NodeInstance(); - nextNode.setWorkflowInstance(currentNode.getWorkflowInstance()); - nextNode.setNodeId(nodeId); - nextNode.setNodeType(nextNodeDef.getType()); - nextNode.setName(nextNodeDef.getName()); - nextNode.setConfig(nextNodeDef.getConfig()); - nextNode.setStatus(NodeStatusEnum.PENDING); - nextNode.setCreateTime(LocalDateTime.now()); - - nodeInstanceRepository.save(nextNode); - - context.log(String.format("创建下一个节点实例: %s[%s]", nextNode.getName(), nextNode.getNodeId()), - LogLevelEnum.INFO); - } + //这里应该从WorkflowDefinition类的transitionConfig获取 } } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeDefinition.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeDefinition.java deleted file mode 100644 index 77f00478..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeDefinition.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.qqchen.deploy.backend.workflow.entity; - -import com.qqchen.deploy.backend.framework.annotation.LogicDelete; -import com.qqchen.deploy.backend.framework.domain.Entity; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import jakarta.persistence.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 节点定义实体 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@jakarta.persistence.Entity -@Table(name = "wf_node_definition") -@LogicDelete -public class NodeDefinition extends Entity { - - /** - * 所属工作流定义 - */ - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "workflow_definition_id", nullable = false) - private WorkflowDefinition workflowDefinition; - - /** - * 节点ID - */ - @Column(name = "node_id", nullable = false) - private String nodeId; - - /** - * 节点名称 - */ - @Column(nullable = false) - private String name; - - /** - * 节点类型 - */ - @Enumerated(EnumType.ORDINAL) - @Column(nullable = false) - private NodeTypeEnum type; - - /** - * 节点配置(JSON) - */ - @Column(columnDefinition = "TEXT") - private String config; - - /** - * 排序号 - */ - @Column(name = "order_num") - private Integer orderNum; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeDefinitionRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeDefinitionRepository.java deleted file mode 100644 index 1e869f2a..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeDefinitionRepository.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.qqchen.deploy.backend.workflow.repository; - -import com.qqchen.deploy.backend.framework.repository.IBaseRepository; -import com.qqchen.deploy.backend.workflow.entity.NodeDefinition; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * 节点定义仓库接口 - */ -@Repository -public interface INodeDefinitionRepository extends IBaseRepository { - - /** - * 根据工作流定义ID查询节点列表 - * - * @param workflowDefinitionId 工作流定义ID - * @return 节点列表 - */ - @Query("SELECT n FROM NodeDefinition n WHERE n.workflowDefinition.id = :workflowDefinitionId AND n.deleted = false ORDER BY n.orderNum") - List findByWorkflowDefinitionId(@Param("workflowDefinitionId") Long workflowDefinitionId); - - /** - * 根据工作流定义ID和节点类型查询节点列表 - * - * @param workflowDefinitionId 工作流定义ID - * @param type 节点类型 - * @return 节点列表 - */ - @Query("SELECT n FROM NodeDefinition n WHERE n.workflowDefinition.id = :workflowDefinitionId AND n.type = :type AND n.deleted = false ORDER BY n.orderNum") - List findByWorkflowDefinitionIdAndType( - @Param("workflowDefinitionId") Long workflowDefinitionId, - @Param("type") NodeTypeEnum type); - - /** - * 根据工作流定义ID和节点ID查询节点 - * - * @param workflowDefinitionId 工作流定义ID - * @param nodeId 节点ID - * @return 节点定义 - */ - @Query("SELECT n FROM NodeDefinition n WHERE n.workflowDefinition.id = :workflowDefinitionId AND n.nodeId = :nodeId AND n.deleted = false") - NodeDefinition findByWorkflowDefinitionIdAndNodeIdAndDeletedFalse( - @Param("workflowDefinitionId") Long workflowDefinitionId, - @Param("nodeId") String nodeId); - - /** - * 检查节点ID是否已存在 - * - * @param workflowDefinitionId 工作流定义ID - * @param nodeId 节点ID - * @return 是否存在 - */ - @Query("SELECT COUNT(n) > 0 FROM NodeDefinition n WHERE n.workflowDefinition.id = :workflowDefinitionId AND n.nodeId = :nodeId AND n.deleted = false") - boolean existsByWorkflowDefinitionIdAndNodeIdAndDeletedFalse( - @Param("workflowDefinitionId") Long workflowDefinitionId, - @Param("nodeId") String nodeId); - - /** - * 删除工作流定义的所有节点 - * - * @param workflowDefinitionId 工作流定义ID - */ - @Query("UPDATE NodeDefinition n SET n.deleted = true WHERE n.workflowDefinition.id = :workflowDefinitionId") - void deleteByWorkflowDefinitionId(@Param("workflowDefinitionId") Long workflowDefinitionId); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDefinitionServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDefinitionServiceImpl.java index c9bde1b6..ef342bfb 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDefinitionServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDefinitionServiceImpl.java @@ -7,7 +7,6 @@ import com.qqchen.deploy.backend.workflow.converter.WorkflowDefinitionConverter; import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum; -import com.qqchen.deploy.backend.workflow.repository.INodeDefinitionRepository; import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository; import com.qqchen.deploy.backend.workflow.service.IWorkflowDefinitionService; import jakarta.annotation.Resource; @@ -30,9 +29,6 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl workflowDefinitionService.create(dto)); - assertEquals(ResponseCode.WORKFLOW_CODE_EXISTS, exception.getErrorCode()); - } - - @Test - void publish_Success() { - entity.setStatus(WorkflowDefinitionStatusEnum.DRAFT); - when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity)); - when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity); - - WorkflowDefinitionDTO result = workflowDefinitionService.publish(1L); - - assertNotNull(result); - assertEquals(WorkflowDefinitionStatusEnum.PUBLISHED, result.getStatus()); - verify(workflowDefinitionRepository).findById(1L); - verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class)); - } - - @Test - void publish_NotDraft_ThrowsException() { - entity.setStatus(WorkflowDefinitionStatusEnum.PUBLISHED); - when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity)); - - BusinessException exception = assertThrows(BusinessException.class, - () -> workflowDefinitionService.publish(1L)); - assertEquals(ResponseCode.WORKFLOW_NOT_DRAFT, exception.getErrorCode()); - } - - @Test - void disable_Success() { - entity.setStatus(WorkflowDefinitionStatusEnum.PUBLISHED); - when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity)); - when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity); - - WorkflowDefinitionDTO result = workflowDefinitionService.disable(1L); - - assertNotNull(result); - assertEquals(WorkflowDefinitionStatusEnum.DISABLED, result.getStatus()); - verify(workflowDefinitionRepository).findById(1L); - verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class)); - } - - @Test - void enable_Success() { - entity.setStatus(WorkflowDefinitionStatusEnum.DISABLED); - when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity)); - when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity); - - WorkflowDefinitionDTO result = workflowDefinitionService.enable(1L); - - assertNotNull(result); - assertEquals(WorkflowDefinitionStatusEnum.PUBLISHED, result.getStatus()); - verify(workflowDefinitionRepository).findById(1L); - verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class)); - } - - @Test - void createNewVersion_Success() { - when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity)); - when(workflowDefinitionRepository.findLatestVersionByCode(anyString())).thenReturn(1); - when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity); - - WorkflowDefinitionDTO result = workflowDefinitionService.createNewVersion(1L); - - assertNotNull(result); - assertEquals(WorkflowDefinitionStatusEnum.DRAFT, result.getStatus()); - assertTrue(result.getEnabled()); - verify(workflowDefinitionRepository).findById(1L); - verify(workflowDefinitionRepository).findLatestVersionByCode(entity.getCode()); - verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class)); - } - - @Test - void findAllVersions_Success() { - when(workflowDefinitionRepository.findAllVersionsByCode(anyString())) - .thenReturn(Arrays.asList(entity)); - - var results = workflowDefinitionService.findAllVersions("TEST-WF"); - - assertNotNull(results); - assertFalse(results.isEmpty()); - assertEquals(1, results.size()); - verify(workflowDefinitionRepository).findAllVersionsByCode("TEST-WF"); - } -} \ No newline at end of file