diff --git a/backend/docs/workflow-engine-design.md b/backend/docs/workflow-engine-design.md new file mode 100644 index 00000000..c94b42e3 --- /dev/null +++ b/backend/docs/workflow-engine-design.md @@ -0,0 +1,670 @@ +# 工作流引擎改造方案设计文档 + +## 1. 现状分析 + +### 1.1 现有组件 + +1. 工作流引擎核心组件 +- `AbstractNodeExecutor`: 节点执行器抽象类,提供基础的节点执行逻辑 +- `WorkflowGraph`: 工作流图模型,管理节点和转换关系 +- `INodeExecutor`: 节点执行器接口 +- `WorkflowInstance`: 工作流实例实体 +- `NodeInstance`: 节点实例实体 + +2. 数据模型 +```sql +-- 工作流定义表 +CREATE TABLE wf_workflow_definition ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + code VARCHAR(100) NOT NULL COMMENT '工作流编码', + name VARCHAR(100) NOT NULL COMMENT '工作流名称', + description VARCHAR(255) NULL COMMENT '工作流描述', + status TINYINT NOT NULL COMMENT '工作流状态(0:草稿,1:已发布,2:已禁用)', + version_no INT NOT NULL DEFAULT 1 COMMENT '版本号', + node_config TEXT NULL COMMENT '节点配置(JSON)', + transition_config TEXT NULL COMMENT '流转配置(JSON)', + form_definition TEXT NULL COMMENT '表单定义(JSON)', + graph_definition TEXT NULL COMMENT '图形信息(JSON)', + enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用', + + CONSTRAINT UK_workflow_definition_code_version UNIQUE (code, version_no) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流定义表'; + +-- 工作流实例表 +CREATE TABLE wf_workflow_instance ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + workflow_definition_id BIGINT NOT NULL COMMENT '工作流定义ID', + business_key VARCHAR(100) NOT NULL COMMENT '业务标识', + status TINYINT NOT NULL COMMENT '状态(0:已创建,1:等待执行,2:执行中,3:已完成,4:执行失败,5:已取消,6:已暂停,7:已终止)', + start_time DATETIME(6) NULL COMMENT '开始时间', + end_time DATETIME(6) NULL COMMENT '结束时间', + error TEXT NULL COMMENT '错误信息', + + CONSTRAINT FK_workflow_instance_definition FOREIGN KEY (workflow_definition_id) REFERENCES wf_workflow_definition (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流实例表'; + +-- 节点实例表 +CREATE TABLE wf_node_instance ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + workflow_instance_id BIGINT NOT NULL COMMENT '工作流实例ID', + node_id VARCHAR(100) NOT NULL COMMENT '节点ID', + node_type TINYINT NOT NULL COMMENT '节点类型(0:开始节点,1:结束节点,2:任务节点,3:网关节点,4:子流程节点,5:Shell脚本节点,6:审批节点,7:Jenkins任务节点,8:Git操作节点)', + name VARCHAR(100) NOT NULL COMMENT '节点名称', + status TINYINT NOT NULL COMMENT '状态(0:已创建,1:等待执行,2:执行中,3:已完成,4:执行失败,5:已取消,6:已暂停,7:已终止)', + start_time DATETIME(6) NULL COMMENT '开始时间', + end_time DATETIME(6) NULL COMMENT '结束时间', + config TEXT NULL COMMENT '节点配置(JSON)', + description TEXT NULL COMMENT '节点描述', + input TEXT NULL COMMENT '输入参数(JSON)', + output TEXT NULL COMMENT '输出结果(JSON)', + error TEXT NULL COMMENT '错误信息', + pre_node_id VARCHAR(100) NULL COMMENT '前置节点ID', + + CONSTRAINT FK_node_instance_workflow FOREIGN KEY (workflow_instance_id) REFERENCES wf_workflow_instance (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='节点实例表'; + +-- 工作流变量表 +CREATE TABLE wf_workflow_variable ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + workflow_instance_id BIGINT NOT NULL COMMENT '工作流实例ID', + name VARCHAR(100) NOT NULL COMMENT '变量名', + value TEXT NULL COMMENT '变量值', + type VARCHAR(20) NOT NULL COMMENT '变量类型', + + CONSTRAINT FK_workflow_variable_instance FOREIGN KEY (workflow_instance_id) REFERENCES wf_workflow_instance (id), + CONSTRAINT UK_workflow_variable_instance_name UNIQUE (workflow_instance_id, name) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流变量表'; + +-- 工作流日志表 +CREATE TABLE wf_log ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + workflow_instance_id BIGINT NOT NULL COMMENT '工作流实例ID', + node_id VARCHAR(50) NULL COMMENT '节点ID', + level VARCHAR(10) NOT NULL COMMENT '日志级别', + message TEXT NOT NULL COMMENT '日志内容', + detail TEXT, + create_time DATETIME NOT NULL, + create_by VARCHAR(50), + update_time DATETIME, + update_by VARCHAR(50), + version INT DEFAULT 0, + deleted BOOLEAN DEFAULT FALSE, + CONSTRAINT FK_workflow_log_instance FOREIGN KEY (workflow_instance_id) REFERENCES wf_workflow_instance (id) +); + +-- 工作流权限表 +CREATE TABLE wf_workflow_permission ( + id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', + workflow_definition_id BIGINT NOT NULL COMMENT '工作流定义ID', + type VARCHAR(50) NOT NULL COMMENT '权限类型', + user_id BIGINT COMMENT '用户ID', + role_id BIGINT COMMENT '角色ID', + department_id BIGINT COMMENT '部门ID', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + create_by BIGINT NOT NULL COMMENT '创建人', + update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + update_by BIGINT NOT NULL COMMENT '更新人', + version INT NOT NULL DEFAULT 0 COMMENT '版本号', + deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除', + INDEX idx_workflow_definition_id (workflow_definition_id), + INDEX idx_user_id (user_id), + INDEX idx_role_id (role_id), + INDEX idx_department_id (department_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工作流权限'; + +-- 节点类型表 +CREATE TABLE wf_node_type ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + code VARCHAR(100) NOT NULL COMMENT '节点类型编码', + name VARCHAR(100) NOT NULL COMMENT '节点类型名称', + description TEXT NULL COMMENT '节点类型描述', + category VARCHAR(50) NOT NULL COMMENT '节点类型分类', + icon VARCHAR(100) NULL COMMENT '节点图标', + color VARCHAR(20) NULL COMMENT '节点颜色', + executors TEXT NULL COMMENT '执行器列表(JSON)', + config_schema TEXT NULL COMMENT '节点配置模式(JSON)', + default_config TEXT NULL COMMENT '默认配置(JSON)', + enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用', + + CONSTRAINT UK_node_type_code UNIQUE (code) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='节点类型表'; + +## 2. 改造目标 + +### 2.1 核心需求 +1. 支持审批节点 +2. 实现实时日志 +3. 工作流状态持久化 +4. 支持程序重启后恢复执行 + +### 2.2 技术要求 +1. 遵循现有代码规范 +2. 保持向后兼容 +3. 确保高可用性 +4. 支持并发执行 + +## 3. 详细设计 + +### 3.1 数据库改造 + +#### 3.1.1 修改现有表 +```sql +-- 修改工作流实例表,添加执行状态字段 +ALTER TABLE wf_workflow_instance +ADD COLUMN current_node_id varchar(100) COMMENT '当前执行的节点ID', +ADD COLUMN execution_status varchar(32) COMMENT '执行状态'; + +-- 修改节点实例表,添加重试相关字段 +ALTER TABLE wf_node_instance +ADD COLUMN retry_count INT DEFAULT 0 COMMENT '重试次数', +ADD COLUMN max_retry_count INT DEFAULT 0 COMMENT '最大重试次数', +ADD COLUMN retry_interval INT DEFAULT 0 COMMENT '重试间隔(秒)', +ADD COLUMN last_retry_time TIMESTAMP COMMENT '最后重试时间'; +``` + +#### 3.1.2 新增审批相关表 +```sql +-- 审批配置表 +CREATE TABLE wf_approval_config ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + project_id VARCHAR(64) NOT NULL COMMENT '项目ID', + env_type VARCHAR(20) NOT NULL COMMENT '环境类型', + approval_type VARCHAR(20) NOT NULL COMMENT '审批类型(SINGLE/MULTI/ANY)', + approver_ids TEXT NOT NULL COMMENT '审批人ID列表(JSON)', + required_count INT NOT NULL COMMENT '需要的审批人数', + timeout_hours INT NOT NULL COMMENT '审批超时时间(小时)', + enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用', + + CONSTRAINT UK_approval_config_project_env UNIQUE (project_id, env_type) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审批配置表'; + +-- 审批实例表 +CREATE TABLE wf_approval_instance ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + node_instance_id VARCHAR(64) NOT NULL COMMENT '节点实例ID', + workflow_instance_id VARCHAR(64) NOT NULL COMMENT '工作流实例ID', + project_id VARCHAR(64) NOT NULL COMMENT '项目ID', + env_type VARCHAR(20) NOT NULL COMMENT '环境类型', + status VARCHAR(20) NOT NULL COMMENT '状态(PENDING/APPROVED/REJECTED/TIMEOUT)', + initiator_id VARCHAR(64) NOT NULL COMMENT '发起人ID', + approved_time DATETIME(6) NULL COMMENT '审批通过时间', + approver_id VARCHAR(64) NULL COMMENT '审批人ID', + comment TEXT NULL COMMENT '审批意见', + + INDEX idx_workflow_instance (workflow_instance_id), + INDEX idx_node_instance (node_instance_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审批实例表'; + +-- 审批记录表 +CREATE TABLE wf_approval_record ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + approval_instance_id BIGINT NOT NULL COMMENT '审批实例ID', + approver_id VARCHAR(64) NOT NULL COMMENT '审批人ID', + action VARCHAR(20) NOT NULL COMMENT '审批动作(APPROVE/REJECT)', + comment TEXT NULL COMMENT '审批意见', + + CONSTRAINT FK_approval_record_instance FOREIGN KEY (approval_instance_id) + REFERENCES wf_approval_instance (id), + INDEX idx_approval_instance (approval_instance_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审批记录表'; + +### 3.2 代码改造 + +#### 3.2.1 新增枚举 +```java +/** + * 节点类型枚举扩展 + */ +public enum NodeTypeEnum { + SCRIPT, // 脚本节点 + HTTP, // HTTP请求节点 + APPROVAL, // 审批节点 + // ... 其他节点类型 +} + +/** + * 审批类型枚举 + */ +public enum ApprovalTypeEnum { + SINGLE, // 单人审批 + MULTI, // 多人会签 + ANY // 任意人审批 +} + +/** + * 审批状态枚举 + */ +public enum ApprovalStatusEnum { + PENDING, // 待审批 + APPROVED, // 已通过 + REJECTED, // 已拒绝 + TIMEOUT // 已超时 +} +``` + +#### 3.2.2 实体类 +```java +/** + * 审批配置实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "wf_approval_config") +@LogicDelete +public class ApprovalConfig extends BaseEntity { + @Column(nullable = false) + private String projectId; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private String envType; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private ApprovalTypeEnum approvalType; + + @Column(nullable = false) + private String approverIds; + + @Column(nullable = false) + private Integer requiredCount; + + @Column(nullable = false) + private Integer timeoutHours; +} + +/** + * 审批实例实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@Table(name = "wf_approval_instance") +@LogicDelete +public class ApprovalInstance extends BaseEntity { + @Column(nullable = false) + private String nodeInstanceId; + + @Column(nullable = false) + private String workflowInstanceId; + + @Column(nullable = false) + private String projectId; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private String envType; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private ApprovalStatusEnum status; + + @Column(nullable = false) + private String initiatorId; + + private LocalDateTime approvedTime; + private String approverId; + private String comment; +} +``` + +#### 3.2.3 Repository接口 +```java +/** + * 审批配置Repository + */ +@Repository +public interface IApprovalConfigRepository extends IBaseRepository { + ApprovalConfig findByProjectIdAndEnvType(String projectId, String envType); +} + +/** + * 审批实例Repository + */ +@Repository +public interface IApprovalInstanceRepository extends IBaseRepository { + List findByStatus(ApprovalStatusEnum status); + ApprovalInstance findByWorkflowInstanceIdAndNodeInstanceId(String workflowInstanceId, String nodeInstanceId); +} +``` + +#### 3.2.4 Service接口 +```java +/** + * 审批服务接口 + */ +public interface IApprovalService { + /** + * 创建审批实例 + */ + ApprovalInstance createApprovalInstance(String nodeInstanceId, String workflowInstanceId, + String projectId, ApprovalConfig config); + + /** + * 处理审批结果 + */ + void handleApproval(Long approvalInstanceId, String approverId, + boolean approved, String comment); + + /** + * 检查审批状态 + */ + ApprovalStatusEnum checkApprovalStatus(Long approvalInstanceId); + + /** + * 发送审批通知 + */ + void sendApprovalNotifications(ApprovalInstance instance); +} +``` + +#### 3.2.5 工作流执行管理器 +```java +/** + * 工作流执行管理器 + */ +@Component +@Slf4j +public class WorkflowExecutionManager { + + @Resource + private ThreadPoolExecutor workflowExecutor; + + @Resource + private WorkflowInstanceRepository instanceRepository; + + @PostConstruct + public void init() { + // 初始化线程池 + workflowExecutor = new ThreadPoolExecutor( + 10, 20, 60L, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(100), + new ThreadFactoryBuilder().setNameFormat("workflow-executor-%d").build() + ); + + // 恢复运行中的工作流 + resumeRunningWorkflows(); + } + + // ... 其他方法实现 +} +``` + +#### 3.2.6 审批节点执行器 +```java +/** + * 审批节点执行器 + */ +@Component +@Slf4j +public class ApprovalNodeExecutor extends AbstractNodeExecutor { + + @Resource + private IApprovalService approvalService; + + @Override + public NodeTypeEnum getNodeType() { + return NodeTypeEnum.APPROVAL; + } + + @Override + protected void doExecute(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { + // ... 实现审批节点执行逻辑 + } +} +``` + +### 3.3 实时日志实现 + +#### 3.3.1 日志收集器 +```java +/** + * 日志收集器 + */ +@Component +@Slf4j +public class ProcessLogManager { + + @Resource + private WorkflowLogService workflowLogService; + + private final Map logBuffers = new ConcurrentHashMap<>(); + private final Map>> subscribers = new ConcurrentHashMap<>(); + + // ... 实现日志收集和推送逻辑 +} +``` + +#### 3.3.2 SSE控制器 +```java +/** + * 日志SSE控制器 + */ +@RestController +@RequestMapping("/api/v1/logs") +@Tag(name = "工作流日志", description = "工作流日志相关接口") +public class LogController { + + @GetMapping(value = "/{nodeInstanceId}/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public SseEmitter streamLogs(@PathVariable String nodeInstanceId) { + // ... 实现SSE日志推送 + } +} +``` + +## 4. 开发计划 + +### 4.1 核心功能改造 + +#### 4.1.1 工作流引擎核心 +1. **状态管理优化** + - 实现工作流实例状态机,支持更细粒度的状态转换 + - 增加节点实例的状态追踪和历史记录 + - 添加工作流暂停/恢复机制 + +2. **并发控制增强** + - 实现基于数据库的分布式锁 + - 添加节点级别的并发控制 + - 优化多实例并行执行的性能 + +3. **错误处理机制** + - 完善节点执行失败的重试机制 + - 实现节点回滚功能 + - 添加全局异常处理和日志记录 + - 支持自定义错误处理策略 + +#### 4.1.2 审批功能实现 +1. **审批节点开发** + - 实现审批节点执行器 + - 支持多种审批模式(单人、多人、任意人) + - 添加审批超时处理机制 + - 实现审批回调通知 + +2. **审批流程管理** + - 开发审批配置管理接口 + - 实现审批人动态配置 + - 支持审批规则的版本控制 + - 添加审批历史查询功能 + +3. **审批UI组件** + - 开发审批任务列表 + - 实现审批详情页面 + - 添加审批操作接口 + - 支持审批意见和附件上传 + +### 4.2 新增功能 + +#### 4.2.1 工作流监控 +1. **实时监控** + - 实现工作流执行状态实时展示 + - 添加节点执行时间统计 + - 支持执行瓶颈分析 + - 实现资源使用监控 + +2. **报警机制** + - 添加执行超时告警 + - 实现错误率监控告警 + - 支持自定义告警规则 + - 集成多种告警通道(邮件、短信、webhook等) + +#### 4.2.2 工作流分析 +1. **统计分析** + - 实现工作流执行趋势分析 + - 添加节点执行效率分析 + - 支持审批效率统计 + - 开发自定义报表功能 + +2. **可视化展示** + - 实现工作流执行路径可视化 + - 添加状态转换图表展示 + - 支持审批流程可视化 + - 开发数据大屏功能 + +### 4.3 性能优化 + +1. **数据库优化** + - 优化表结构和索引 + - 实现分库分表方案 + - 添加缓存机制 + - 优化大数据量查询性能 + +2. **执行引擎优化** + - 优化线程池管理 + - 实现节点执行预热 + - 添加资源限流机制 + - 优化内存使用 + +### 4.4 开发排期 + +#### Phase 1: 核心功能改造(4周) +- Week 1-2: 工作流引擎核心改造 +- Week 3-4: 审批功能实现 + +#### Phase 2: 新增功能开发(3周) +- Week 1-2: 工作流监控功能 +- Week 3: 工作流分析功能 + +#### Phase 3: 性能优化(2周) +- Week 1: 数据库优化 +- Week 2: 执行引擎优化 + +#### Phase 4: 测试与上线(1周) +- Day 1-3: 功能测试与bug修复 +- Day 4-5: 性能测试与优化 +- Day 6-7: 准备上线与部署 + +### 4.5 风险评估 + +1. **技术风险** + - 分布式环境下的状态一致性 + - 大规模并发下的性能表现 + - 复杂工作流的稳定性保证 + +2. **项目风险** + - 开发周期可能超出预期 + - 新旧版本兼容性问题 + - 现有业务的平滑迁移 + +### 4.6 后续规划 + +1. **功能扩展** + - 支持更多类型的节点 + - 添加工作流模板功能 + - 实现工作流版本管理 + - 支持跨系统工作流 + +2. **生态建设** + - 开发SDK工具包 + - 提供更多开箱即用的组件 + - 完善开发文档 + - 建设示例中心 + +## 5. 注意事项 + +1. 数据迁移 +- 需要处理已有的运行中工作流 +- 确保数据一致性 + +2. 性能考虑 +- 控制线程池大小 +- 合理设置日志缓冲区 +- 定期清理历史数据 + +3. 监控告警 +- 添加工作流执行监控 +- 配置审批超时告警 +- 监控系统资源使用 + +## 6. 后续优化 + +1. 功能优化 +- 支持更多审批策略 +- 优化日志查询性能 +- 添加工作流统计分析 + +2. 性能优化 +- 引入分布式锁 +- 优化数据库查询 +- 添加缓存机制 + +3. 运维优化 +- 完善监控指标 +- 优化日志清理 +- 添加性能诊断工具 diff --git a/backend/pom.xml b/backend/pom.xml index c3af167a..df1607f2 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -26,6 +26,7 @@ 0.12.3 2.2.0 5.8.23 + 7.0.0 @@ -201,6 +202,17 @@ caffeine 3.1.8 + + + org.flowable + flowable-spring-boot-starter + ${flowable.version} + + + org.flowable + flowable-bpmn-layout + ${flowable.version} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/NodeInstanceApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/NodeInstanceApiController.java deleted file mode 100644 index 973a88b3..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/NodeInstanceApiController.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.qqchen.deploy.backend.workflow.api; - -import com.qqchen.deploy.backend.framework.controller.BaseController; -import com.qqchen.deploy.backend.workflow.dto.NodeInstanceDTO; -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.query.NodeInstanceQuery; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@Slf4j -@RestController -@RequestMapping("/api/v1/node-instances") -@Tag(name = "节点实例管理", description = "节点实例管理相关接口") -public class NodeInstanceApiController extends BaseController { - - @Override - protected void exportData(HttpServletResponse response, List data) { - - } -} - diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/NodeTypeApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/NodeTypeApiController.java deleted file mode 100644 index 9e37a3e4..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/NodeTypeApiController.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.qqchen.deploy.backend.workflow.api; - -import com.qqchen.deploy.backend.framework.controller.BaseController; -import com.qqchen.deploy.backend.workflow.dto.NodeTypeDTO; -import com.qqchen.deploy.backend.workflow.dto.query.NodeTypeQuery; -import com.qqchen.deploy.backend.workflow.entity.NodeType; -import com.qqchen.deploy.backend.workflow.service.INodeTypeService; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; - -/** - * 节点类型接口 - */ -@Slf4j -@Tag(name = "节点类型管理", description = "节点类型相关接口") -@RestController -@RequestMapping("/api/v1/node-types") -public class NodeTypeApiController extends BaseController { - - @Resource - private INodeTypeService nodeTypeService; - - @Override - protected void exportData(HttpServletResponse response, List data) { - - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowDefinitionApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowDefinitionApiController.java deleted file mode 100644 index 6a4101a5..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowDefinitionApiController.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.qqchen.deploy.backend.workflow.api; - -import com.qqchen.deploy.backend.framework.api.Response; -import com.qqchen.deploy.backend.framework.controller.BaseController; -import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import com.qqchen.deploy.backend.workflow.query.WorkflowDefinitionQuery; -import com.qqchen.deploy.backend.workflow.service.IWorkflowDefinitionService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@Slf4j -@RestController -@RequestMapping("/api/v1/workflow-definitions") -@Tag(name = "工作流定义管理", description = "工作流定义管理相关接口") -public class WorkflowDefinitionApiController extends BaseController { - - @Resource - private IWorkflowDefinitionService workflowDefinitionService; - - @Operation(summary = "发布工作流") - @PostMapping("/{id}/publish") - public Response publish( - @Parameter(description = "工作流定义ID", required = true) @PathVariable Long id - ) { - workflowDefinitionService.publish(id); - return Response.success(); - } - - @Operation(summary = "禁用工作流") - @PostMapping("/{id}/disable") - public Response disable( - @Parameter(description = "工作流定义ID", required = true) @PathVariable Long id - ) { - workflowDefinitionService.disable(id); - return Response.success(); - } - - @Operation(summary = "启用工作流") - @PostMapping("/{id}/enable") - public Response enable( - @Parameter(description = "工作流定义ID", required = true) @PathVariable Long id - ) { - workflowDefinitionService.enable(id); - return Response.success(); - } - - @Override - protected void exportData(HttpServletResponse response, List data) { - - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowInstanceApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowInstanceApiController.java deleted file mode 100644 index 518e484d..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowInstanceApiController.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.qqchen.deploy.backend.workflow.api; - -import com.qqchen.deploy.backend.framework.api.Response; -import com.qqchen.deploy.backend.framework.controller.BaseController; -import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceDTO; -import com.qqchen.deploy.backend.workflow.dto.request.WorkflowStartRequest; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.service.IWorkflowEngineService; -import com.qqchen.deploy.backend.workflow.query.WorkflowInstanceQuery; -import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService; -import com.qqchen.deploy.backend.workflow.converter.WorkflowInstanceConverter; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.Map; - -@Slf4j -@RestController -@RequestMapping("/api/v1/workflow-instances") -@Tag(name = "工作流实例管理", description = "工作流实例管理相关接口") -public class WorkflowInstanceApiController extends BaseController { - - @Resource - private IWorkflowEngineService workflowEngine; - - @Resource - private IWorkflowInstanceService workflowInstanceService; - - @Resource - private WorkflowInstanceConverter converter; - - @Operation(summary = "启动工作流实例") - @PostMapping("/start") - public Response startWorkflow(@RequestBody WorkflowStartRequest request) { - return Response.success(converter.toDto(workflowEngine.startWorkflow(request))); - } - - - @Override - public void exportData(HttpServletResponse response, List data) { - // TODO: 实现导出功能 - } - - -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowLogApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowLogApiController.java deleted file mode 100644 index 79d4d6b4..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowLogApiController.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.qqchen.deploy.backend.workflow.api; - -import com.qqchen.deploy.backend.system.enums.LogLevelEnum; -import com.qqchen.deploy.backend.framework.api.Response; -import com.qqchen.deploy.backend.framework.controller.BaseController; -import com.qqchen.deploy.backend.workflow.dto.WorkflowLogDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowLog; -import com.qqchen.deploy.backend.workflow.query.WorkflowLogQuery; -import com.qqchen.deploy.backend.workflow.service.IWorkflowLogService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@Slf4j -@RestController -@RequestMapping("/api/v1/workflow-logs") -@Tag(name = "工作流日志管理", description = "工作流日志管理相关接口") -public class WorkflowLogApiController extends BaseController { - - @Resource - private IWorkflowLogService workflowLogService; - - @Operation(summary = "查询工作流实例日志") - @GetMapping("/workflow/{workflowInstanceId}") - public Response> getWorkflowLogs( - @Parameter(description = "工作流实例ID", required = true) @PathVariable Long workflowInstanceId - ) { - return Response.success(workflowLogService.getLogs(workflowInstanceId)); - } - - @Operation(summary = "查询节点实例日志") - @GetMapping("/node/{workflowInstanceId}/{nodeId}") - public Response> getNodeLogs( - @Parameter(description = "工作流实例ID", required = true) @PathVariable Long workflowInstanceId, - @Parameter(description = "节点ID", required = true) @PathVariable String nodeId - ) { - return Response.success(workflowLogService.getNodeLogs(workflowInstanceId, nodeId)); - } - - @Operation(summary = "记录日志") - @PostMapping("/record") - public Response recordLog( - @Parameter(description = "工作流实例ID", required = true) @RequestParam Long workflowInstanceId, - @Parameter(description = "节点ID") @RequestParam(required = false) String nodeId, - @Parameter(description = "日志内容", required = true) @RequestParam String message, - @Parameter(description = "日志级别", required = true) @RequestParam LogLevelEnum level, - @Parameter(description = "详细信息") @RequestParam(required = false) String detail - ) { - workflowLogService.recordLog(workflowInstanceId, nodeId, message, level, detail); - return Response.success(); - } - - @Override - public void exportData(HttpServletResponse response, List data) { - // TODO: 实现导出功能 - } - -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/config/FlowableConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/config/FlowableConfig.java new file mode 100644 index 00000000..3e869b5d --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/config/FlowableConfig.java @@ -0,0 +1,20 @@ +package com.qqchen.deploy.backend.workflow.config; + +import org.flowable.spring.SpringProcessEngineConfiguration; +import org.flowable.spring.boot.EngineConfigurationConfigurer; +import org.springframework.context.annotation.Configuration; + +/** + * Flowable配置类 + */ +@Configuration +public class FlowableConfig implements EngineConfigurationConfigurer { + + @Override + public void configure(SpringProcessEngineConfiguration engineConfiguration) { + engineConfiguration.setActivityFontName("宋体"); + engineConfiguration.setLabelFontName("宋体"); + engineConfiguration.setAnnotationFontName("宋体"); + engineConfiguration.setDatabaseSchemaUpdate("true"); + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/controller/WorkflowDefinitionController.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/controller/WorkflowDefinitionController.java new file mode 100644 index 00000000..245857e6 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/controller/WorkflowDefinitionController.java @@ -0,0 +1,72 @@ +package com.qqchen.deploy.backend.workflow.controller; + +import com.qqchen.deploy.backend.framework.api.Response; +import com.qqchen.deploy.backend.framework.controller.BaseController; +import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO; +import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; +import com.qqchen.deploy.backend.workflow.query.WorkflowDefinitionQuery; +import com.qqchen.deploy.backend.workflow.service.IWorkflowDefinitionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.runtime.ProcessInstance; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 工作流定义控制器 + */ +@Slf4j +@RestController +@RequestMapping("/api/v1/workflow/definition") +@Tag(name = "工作流定义管理", description = "工作流定义管理相关接口") +public class WorkflowDefinitionController extends BaseController { + + @Resource + private IWorkflowDefinitionService workflowDefinitionService; + + @Operation(summary = "部署工作流") + @PostMapping("/deploy") + public Response deployWorkflow(@RequestBody WorkflowDefinitionDTO dto) { + return Response.success(workflowDefinitionService.deployWorkflow(dto)); + } + + @Operation(summary = "启动工作流实例") + @PostMapping("/start") + public Response startWorkflow( + @Parameter(description = "流程标识", required = true) @RequestParam String processKey, + @Parameter(description = "业务标识", required = true) @RequestParam String businessKey, + @Parameter(description = "流程变量") @RequestBody(required = false) Map variables + ) { + ProcessInstance instance = workflowDefinitionService.startWorkflow(processKey, businessKey, variables); + return Response.success(instance.getId()); + } + + @Operation(summary = "挂起工作流实例") + @PostMapping("/{processInstanceId}/suspend") + public Response suspendWorkflow( + @Parameter(description = "流程实例ID", required = true) @PathVariable String processInstanceId + ) { + workflowDefinitionService.suspendWorkflow(processInstanceId); + return Response.success(); + } + + @Operation(summary = "恢复工作流实例") + @PostMapping("/{processInstanceId}/resume") + public Response resumeWorkflow( + @Parameter(description = "流程实例ID", required = true) @PathVariable String processInstanceId + ) { + workflowDefinitionService.resumeWorkflow(processInstanceId); + return Response.success(); + } + + @Override + protected void exportData(HttpServletResponse response, List data) { + + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/controller/WorkflowDesignController.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/controller/WorkflowDesignController.java new file mode 100644 index 00000000..b01dea59 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/controller/WorkflowDesignController.java @@ -0,0 +1,40 @@ +package com.qqchen.deploy.backend.workflow.controller; + +import com.qqchen.deploy.backend.framework.api.Response; +import com.qqchen.deploy.backend.framework.controller.BaseController; +import com.qqchen.deploy.backend.workflow.dto.WorkflowDesignDTO; +import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; +import com.qqchen.deploy.backend.workflow.query.WorkflowDefinitionQuery; +import com.qqchen.deploy.backend.workflow.service.IWorkflowDesignService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 工作流设计控制器 + */ +@Slf4j +@RestController +@RequestMapping("/api/v1/workflow/design") +@Tag(name = "工作流设计", description = "工作流设计相关接口") +public class WorkflowDesignController extends BaseController { + + @Resource + private IWorkflowDesignService workflowDesignService; + + @Operation(summary = "保存工作流设计") + @PostMapping("/save") + public Response saveWorkflowDesign(@RequestBody WorkflowDesignDTO dto) throws Exception { + return Response.success(workflowDesignService.saveWorkflowDesign(dto)); + } + + @Override + protected void exportData(HttpServletResponse response, List data) { + // TODO: 实现导出功能 + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/JsonConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/JsonConverter.java deleted file mode 100644 index 68061548..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/JsonConverter.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter; - -import com.qqchen.deploy.backend.workflow.engine.definition.NodeExecutorDefinition; - -import java.util.List; - -/** - * JSON转换器接口 - * 用于处理系统中的JSON序列化和反序列化 - */ -public interface JsonConverter { - - /** - * 将JSON字符串转换为执行器定义列表 - * - * @param json JSON字符串 - * @return 执行器定义列表 - */ - List toExecutorList(String json); - - /** - * 将执行器定义列表转换为JSON字符串 - * - * @param executors 执行器定义列表 - * @return JSON字符串 - */ - String fromExecutorList(List executors); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/JsonObjectConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/JsonObjectConverter.java deleted file mode 100644 index 83fa5ad0..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/JsonObjectConverter.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.persistence.AttributeConverter; -import jakarta.persistence.Converter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; - -/** - * JSON对象转换器 - * 用于在数据库字符串和Java对象之间进行转换 - */ -@Slf4j -@Converter -public class JsonObjectConverter implements AttributeConverter { - - private static final ObjectMapper objectMapper = new ObjectMapper(); - - @Override - public String convertToDatabaseColumn(Object attribute) { - if (attribute == null) { - return null; - } - try { - return objectMapper.writeValueAsString(attribute); - } catch (JsonProcessingException e) { - log.error("Error converting object to json string", e); - return null; - } - } - - @Override - public Object convertToEntityAttribute(String dbData) { - if (!StringUtils.hasText(dbData)) { - return null; - } - try { - return objectMapper.readValue(dbData, Object.class); - } catch (JsonProcessingException e) { - log.error("Error converting json string to object", e); - return null; - } - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeInstanceConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeInstanceConverter.java deleted file mode 100644 index 243302f7..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeInstanceConverter.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter; - -import com.qqchen.deploy.backend.framework.converter.BaseConverter; -import com.qqchen.deploy.backend.workflow.dto.NodeInstanceDTO; -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * 节点实例转换器 - */ -@Mapper(config = BaseConverter.class) -public interface NodeInstanceConverter extends BaseConverter { - - @Override - @Mapping(target = "nodeId", source = "nodeId") - @Mapping(target = "nodeType", source = "nodeType") - @Mapping(target = "name", source = "name") - @Mapping(target = "status", source = "status") - @Mapping(target = "startTime", source = "startTime") - @Mapping(target = "endTime", source = "endTime") - @Mapping(target = "config", source = "config") - @Mapping(target = "input", source = "input") - @Mapping(target = "output", source = "output") - @Mapping(target = "error", source = "error") - @Mapping(target = "preNodeId", source = "preNodeId") - NodeInstanceDTO toDto(NodeInstance entity); - - @Override - @Mapping(target = "workflowInstance", ignore = true) - @Mapping(target = "nodeId", source = "nodeId") - @Mapping(target = "nodeType", source = "nodeType") - @Mapping(target = "name", source = "name") - @Mapping(target = "status", source = "status") - @Mapping(target = "startTime", source = "startTime") - @Mapping(target = "endTime", source = "endTime") - @Mapping(target = "config", source = "config") - @Mapping(target = "input", source = "input") - @Mapping(target = "output", source = "output") - @Mapping(target = "error", source = "error") - @Mapping(target = "preNodeId", source = "preNodeId") - NodeInstance toEntity(NodeInstanceDTO dto); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeTypeConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeTypeConverter.java deleted file mode 100644 index bd5f313e..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/NodeTypeConverter.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter; - -import com.qqchen.deploy.backend.framework.converter.BaseConverter; -import com.qqchen.deploy.backend.workflow.dto.NodeTypeDTO; -import com.qqchen.deploy.backend.workflow.entity.NodeType; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.MappingTarget; -import org.springframework.beans.factory.annotation.Autowired; - -/** - * 节点类型转换器 - */ -@Mapper(config = BaseConverter.class, componentModel = "spring", uses = {JsonConverter.class}) -public abstract class NodeTypeConverter implements BaseConverter { - - @Autowired - protected JsonConverter jsonConverter; - - @Override - @Mapping(target = "executors", expression = "java(jsonConverter.toExecutorList(entity.getExecutors()))") - public abstract NodeTypeDTO toDto(NodeType entity); - - @Override - @Mapping(target = "executors", expression = "java(jsonConverter.fromExecutorList(dto.getExecutors()))") - public abstract NodeType toEntity(NodeTypeDTO dto); - - @Override - public void updateEntity(NodeType entity, NodeTypeDTO dto) { - // 使用MapStruct生成的更新方法 - updateEntityInternal(entity, dto); - } - - @Mapping(target = "executors", expression = "java(jsonConverter.fromExecutorList(dto.getExecutors()))") - protected abstract void updateEntityInternal(@MappingTarget NodeType entity, NodeTypeDTO dto); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowDefinitionConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowDefinitionConverter.java index a54dfbab..bd8da955 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowDefinitionConverter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowDefinitionConverter.java @@ -8,6 +8,6 @@ import org.mapstruct.Mapper; /** * 工作流定义转换器 */ -@Mapper(componentModel = "spring") +@Mapper(config = BaseConverter.class) public interface WorkflowDefinitionConverter extends BaseConverter { -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowInstanceConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowInstanceConverter.java deleted file mode 100644 index f5181561..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowInstanceConverter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter; - -import com.qqchen.deploy.backend.framework.converter.BaseConverter; -import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * 工作流实例转换器 - */ -@Mapper(config = BaseConverter.class) -public interface WorkflowInstanceConverter extends BaseConverter { - - @Override - @Mapping(target = "definitionId", source = "workflowDefinition.id") - WorkflowInstanceDTO toDto(WorkflowInstance entity); - - @Override - @Mapping(target = "workflowDefinition.id", source = "definitionId") - WorkflowInstance toEntity(WorkflowInstanceDTO dto); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowLogConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowLogConverter.java deleted file mode 100644 index 97ce2971..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowLogConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter; - -import com.qqchen.deploy.backend.framework.converter.BaseConverter; -import com.qqchen.deploy.backend.workflow.dto.WorkflowLogDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowLog; -import org.mapstruct.Mapper; - -/** - * 工作流日志转换器 - */ -@Mapper(config = BaseConverter.class) -public interface WorkflowLogConverter extends BaseConverter { -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowVariableConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowVariableConverter.java deleted file mode 100644 index d7b7af3a..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowVariableConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter; - -import com.qqchen.deploy.backend.framework.converter.BaseConverter; -import com.qqchen.deploy.backend.workflow.dto.WorkflowVariableDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowVariable; -import org.mapstruct.Mapper; - -/** - * 工作流变量转换器 - */ -@Mapper(config = BaseConverter.class) -public interface WorkflowVariableConverter extends BaseConverter { -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/impl/DefaultJsonConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/impl/DefaultJsonConverter.java deleted file mode 100644 index 9b3b4e66..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/impl/DefaultJsonConverter.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.qqchen.deploy.backend.workflow.converter.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.framework.exception.SystemException; -import com.qqchen.deploy.backend.workflow.converter.JsonConverter; -import com.qqchen.deploy.backend.workflow.engine.definition.NodeExecutorDefinition; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; - -/** - * JSON转换器默认实现 - * 使用Jackson进行JSON序列化和反序列化 - */ -@Component -public class DefaultJsonConverter implements JsonConverter { - - private final ObjectMapper objectMapper; - - public DefaultJsonConverter(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } - - @Override - public List toExecutorList(String json) { - if (json == null || json.isEmpty()) { - return new ArrayList<>(); - } - try { - // 先将JSON解析为JsonNode,以便我们可以手动处理configSchema字段 - JsonNode rootNode = objectMapper.readTree(json); - if (!rootNode.isArray()) { - throw new SystemException(ResponseCode.WORKFLOW_CONFIG_INVALID, new Object[]{"Executors JSON must be an array"}, null); - } - - List result = new ArrayList<>(); - for (JsonNode node : rootNode) { - // 将configSchema转换为字符串 - if (node.has("configSchema")) { - ((ObjectNode) node).put("configSchema", node.get("configSchema").toString()); - } - // 将处理后的节点转换为TaskExecutorDefinition对象 - result.add(objectMapper.treeToValue(node, NodeExecutorDefinition.class)); - } - return result; - } catch (JsonProcessingException e) { - throw new SystemException(ResponseCode.WORKFLOW_CONFIG_INVALID, new Object[]{"Failed to parse executors JSON: " + e.getMessage()}, e); - } - } - - @Override - public String fromExecutorList(List executors) { - if (executors == null || executors.isEmpty()) { - return "[]"; - } - try { - return objectMapper.writeValueAsString(executors); - } catch (JsonProcessingException e) { - throw new SystemException("Failed to serialize executors: " + e.getMessage(), e); - } - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/delegate/SimpleTaskDelegate.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/delegate/SimpleTaskDelegate.java new file mode 100644 index 00000000..0cc428d8 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/delegate/SimpleTaskDelegate.java @@ -0,0 +1,29 @@ +package com.qqchen.deploy.backend.workflow.delegate; + +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +/** + * 简单任务委托实现 + */ +@Slf4j +@Component +public class SimpleTaskDelegate implements JavaDelegate { + + @Override + public void execute(DelegateExecution execution) { + String taskName = execution.getCurrentFlowElement().getName(); + log.info("Executing task: {}", taskName); + + // 获取流程变量 + String input = (String) execution.getVariable("input"); + log.info("Task input: {}", input); + + // 设置输出变量 + execution.setVariable("output", "Processed: " + input); + + log.info("Task completed: {}", taskName); + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeDefinitionDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeDefinitionDTO.java deleted file mode 100644 index c1d8404d..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeDefinitionDTO.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto; - -import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 节点定义DTO - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class NodeDefinitionDTO extends BaseDTO { - - /** - * 节点ID - */ - @NotBlank(message = "节点ID不能为空") - private String nodeId; - - /** - * 节点名称 - */ - @NotBlank(message = "节点名称不能为空") - private String name; - - /** - * 节点类型 - */ - @NotNull(message = "节点类型不能为空") - private NodeTypeEnum type; - - /** - * 节点配置(JSON) - */ - private String config; - - /** - * 节点描述 - */ - private String description; - - /** - * 工作流定义ID - */ - @NotNull(message = "工作流定义ID不能为空") - private Long workflowDefinitionId; - - /** - * 排序号 - */ - private Integer orderNum; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeInstanceDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeInstanceDTO.java deleted file mode 100644 index 395494e8..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeInstanceDTO.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto; - -import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDateTime; - -/** - * 节点实例DTO - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class NodeInstanceDTO extends BaseDTO { - - /** - * 工作流实例ID - */ - @NotNull(message = "工作流实例ID不能为空") - private Long workflowInstanceId; - - /** - * 节点ID - */ - @NotBlank(message = "节点ID不能为空") - private String nodeId; - - /** - * 节点类型 - */ - @NotNull(message = "节点类型不能为空") - private NodeTypeEnum nodeType; - - /** - * 节点名称 - */ - @NotBlank(message = "节点名称不能为空") - private String name; - - /** - * 节点状态 - */ - @NotNull(message = "节点状态不能为空") - private NodeStatusEnum status; - - /** - * 开始时间 - */ - private LocalDateTime startTime; - - /** - * 结束时间 - */ - private LocalDateTime endTime; - - /** - * 节点配置(JSON) - */ - private String config; - - /** - * 节点描述 - */ - private String description; - - /** - * 输入参数(JSON) - */ - private String input; - - /** - * 输出结果(JSON) - */ - private String output; - - /** - * 错误信息 - */ - private String error; - - /** - * 前置节点ID - */ - private String preNodeId; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeTypeDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeTypeDTO.java deleted file mode 100644 index c93c8ddd..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/NodeTypeDTO.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto; - -import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.workflow.engine.definition.NodeExecutorDefinition; -import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnum; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -/** - * 节点类型DTO - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class NodeTypeDTO extends BaseDTO { - - /** - * 节点类型编码 - */ - @NotBlank(message = "节点类型编码不能为空") - private String code; - - /** - * 节点类型名称 - */ - @NotBlank(message = "节点类型名称不能为空") - private String name; - - /** - * 节点类型描述 - */ - private String description; - - /** - * 节点类型分类 - */ - @NotNull(message = "节点类型分类不能为空") - private NodeCategoryEnum category; - - /** - * 节点图标 - */ - private String icon; - - /** - * 节点颜色 - */ - private String color; - - /** - * 任务执行器定义列表 - * 定义该节点类型支持的所有任务执行器 - * 说明: - * 1. 只有TASK类型的节点才需要配置执行器 - * 2. 一个任务节点可以支持多种执行器 - * 3. 每种执行器都有自己的配置模式 - */ - @Valid - private List executors; - - /** - * 节点配置模式(JSON) - * 使用JSON Schema格式定义节点的配置结构 - * 说明: - * 1. 基础配置:所有类型节点都需要的配置(如节点名称、描述等) - * 2. 分类配置:不同分类节点特有的配置 - * - TASK:任务节点配置(如执行器选择、重试策略等) - * - GATEWAY:网关节点配置(如条件表达式、分支策略等) - * - EVENT:事件节点配置(如事件类型、触发条件等) - */ - private String configSchema; - - /** - * 默认配置(JSON) - * 符合configSchema定义的默认配置值 - */ - private String defaultConfig; - - /** - * 是否启用 - */ - @NotNull(message = "是否启用不能为空") - private Boolean enabled = true; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDefinitionDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDefinitionDTO.java index ab2e537d..d8c23df2 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDefinitionDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDefinitionDTO.java @@ -1,9 +1,6 @@ package com.qqchen.deploy.backend.workflow.dto; import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; @@ -13,62 +10,29 @@ import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) public class WorkflowDefinitionDTO extends BaseDTO { - + /** - * 工作流编码 + * 流程名称 */ - @NotBlank(message = "工作流编码不能为空") - private String code; - - /** - * 工作流名称 - */ - @NotBlank(message = "工作流名称不能为空") private String name; - + /** - * 工作流描述 + * 流程标识 */ - private String description; - + private String key; + /** - * 工作流状态 - */ - private WorkflowDefinitionStatusEnum status; - - /** - * 版本号 + * 流程版本 */ private Integer version; - + /** - * 节点配置(JSON) + * BPMN XML内容 */ - private String nodeConfig; - + private String bpmnXml; + /** - * 流转配置(JSON) + * 流程描述 */ - private String transitionConfig; - - /** - * 表单定义(JSON) - */ - private String formDefinition; - - /** - * 图形信息(JSON) - */ - private String graphDefinition; - - /** - * 是否启用 - */ - @NotNull(message = "是否启用不能为空") - private Boolean enabled = true; - - /** - * 备注 - */ - private String remark; -} \ No newline at end of file + private String description; +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDesignDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDesignDTO.java new file mode 100644 index 00000000..1ed09c9f --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDesignDTO.java @@ -0,0 +1,30 @@ +package com.qqchen.deploy.backend.workflow.dto; + +import com.qqchen.deploy.backend.framework.dto.BaseDTO; +import lombok.Data; + +/** + * 工作流设计DTO + */ +@Data +public class WorkflowDesignDTO extends BaseDTO { + /** + * 流程名称 + */ + private String name; + + /** + * 流程标识 + */ + private String key; + + /** + * 流程描述 + */ + private String description; + + /** + * 流程图数据 + */ + private String graphJson; +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowInstanceDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowInstanceDTO.java deleted file mode 100644 index 0bb20128..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowInstanceDTO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto; - -import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnum; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDateTime; - -@Data -@EqualsAndHashCode(callSuper = true) -public class WorkflowInstanceDTO extends BaseDTO { - - /** - * 工作流定义ID - */ - @NotNull(message = "工作流定义ID不能为空") - private Long definitionId; - - /** - * 业务标识 - */ - @NotNull(message = "业务标识不能为空") - private String businessKey; - - /** - * 工作流状态 - */ - private WorkflowInstanceStatusEnum status; - - /** - * 开始时间 - */ - private LocalDateTime startTime; - - /** - * 结束时间 - */ - private LocalDateTime endTime; - - /** - * 工作流变量(JSON) - */ - private String variables; - - /** - * 错误信息 - */ - private String error; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowLogDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowLogDTO.java deleted file mode 100644 index be4b9454..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowLogDTO.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto; - -import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.system.enums.LogLevelEnum; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDateTime; - -/** - * 工作流日志DTO - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class WorkflowLogDTO extends BaseDTO { - - /** - * 节点ID - */ - private String nodeId; - - /** - * 日志级别 - */ - private LogLevelEnum level; - - /** - * 日志内容 - */ - private String message; - - /** - * 详细信息 - */ - private String detail; - - /** - * 创建时间 - */ - private LocalDateTime createTime; - - /** - * 创建人 - */ - private String createBy; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowVariableDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowVariableDTO.java deleted file mode 100644 index dad46991..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowVariableDTO.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto; - -import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 工作流变量DTO - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class WorkflowVariableDTO extends BaseDTO { - - /** - * 工作流实例ID - */ - @NotNull(message = "工作流实例ID不能为空") - private Long workflowInstanceId; - - /** - * 变量名称 - */ - @NotBlank(message = "变量名称不能为空") - private String name; - - /** - * 变量值(JSON) - */ - @NotBlank(message = "变量值不能为空") - private String value; - - /** - * 变量类型 - */ - @NotBlank(message = "变量类型不能为空") - private String type; - - /** - * 变量作用域 - */ - @NotBlank(message = "变量作用域不能为空") - private String scope; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/NodeInstanceQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/NodeInstanceQuery.java deleted file mode 100644 index 9bd9a6a5..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/NodeInstanceQuery.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto.query; - -import com.qqchen.deploy.backend.framework.annotation.QueryField; -import com.qqchen.deploy.backend.framework.enums.QueryType; -import com.qqchen.deploy.backend.framework.query.BaseQuery; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 节点实例查询条件 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class NodeInstanceQuery extends BaseQuery { - - /** - * 工作流实例ID - */ - @QueryField(field = "workflowInstanceId") - private Long workflowInstanceId; - - /** - * 节点ID - */ - @QueryField(field = "nodeId", type = QueryType.LIKE) - private String nodeId; - - /** - * 节点类型 - */ - @QueryField(field = "nodeType") - private NodeTypeEnum nodeType; - - /** - * 节点名称 - */ - @QueryField(field = "name", type = QueryType.LIKE) - private String name; - - /** - * 节点状态 - */ - @QueryField(field = "status") - private NodeStatusEnum status; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/NodeTypeQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/NodeTypeQuery.java deleted file mode 100644 index e96f2ae2..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/NodeTypeQuery.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto.query; - -import com.qqchen.deploy.backend.framework.annotation.QueryField; -import com.qqchen.deploy.backend.framework.enums.QueryType; -import com.qqchen.deploy.backend.framework.query.BaseQuery; -import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnum; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 节点类型查询对象 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class NodeTypeQuery extends BaseQuery { - - /** - * 节点类型编码 - */ - @QueryField(field = "code", type = QueryType.LIKE) - private String code; - - /** - * 节点类型名称 - */ - @QueryField(field = "name", type = QueryType.LIKE) - private String name; - - /** - * 节点类型分类 - */ - @QueryField(field = "category") - private NodeCategoryEnum category; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/request/WorkflowStartRequest.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/request/WorkflowStartRequest.java deleted file mode 100644 index 5adf7f63..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/request/WorkflowStartRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto.request; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -import java.util.Map; - -@Data -public class WorkflowStartRequest { - - @NotBlank(message = "工作流编码") - private String workflowCode; - - @NotBlank(message = "业务标识") - private String businessKey; - - @NotBlank(message = "环境变量") - private Map variables; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/config/WorkflowEngineConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/config/WorkflowEngineConfig.java deleted file mode 100644 index f74f0426..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/config/WorkflowEngineConfig.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.config; - -import com.qqchen.deploy.backend.workflow.engine.executor.INodeExecutor; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Configuration -public class WorkflowEngineConfig { - - @Bean - public Map nodeExecutorMap(List executors) { - return executors.stream() - .collect(Collectors.toMap( - INodeExecutor::getNodeType, - Function.identity() - )); - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/definition/NodeExecutorDefinition.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/definition/NodeExecutorDefinition.java deleted file mode 100644 index bae6b3e1..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/definition/NodeExecutorDefinition.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.definition; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -@Data -public class NodeExecutorDefinition { - - @NotBlank(message = "执行器编码不能为空") - private String code; - - /** - * 执行器名称 - * 用于前端展示,应该是用户友好的名称 - * 例如: - * - Shell脚本执行器 - * - Jenkins构建执行器 - * - HTTP接口调用执行器 - */ - @NotBlank(message = "执行器名称不能为空") - private String name; - - /** - * 执行器描述 - * 详细说明执行器的: - * 1. 主要功能和使用场景 - * 2. 配置参数说明 - * 3. 注意事项和限制条件 - */ - private String description; - - /** - * 执行器配置模式 - * 使用JSON Schema格式定义执行器的配置结构 - * 用于: - * 1. 前端动态渲染配置表单 - * 2. 后端验证配置参数 - * - * 示例 - Shell执行器配置模式: - * { - * "type": "object", - * "required": ["script"], - * "properties": { - * "script": { - * "type": "string", - * "title": "脚本内容", - * "format": "shell", - * "description": "需要执行的Shell脚本内容" - * }, - * "timeout": { - * "type": "number", - * "title": "超时时间", - * "description": "脚本执行的最大时间(秒)", - * "minimum": 1, - * "maximum": 3600, - * "default": 300 - * }, - * "workingDir": { - * "type": "string", - * "title": "工作目录", - * "description": "脚本执行的工作目录", - * "default": "/tmp" - * } - * } - * } - */ - private String configSchema; - - /** - * 默认配置 - * 符合configSchema定义的默认配置值 - * 用于: - * 1. 新建节点时的默认值 - * 2. 重置配置时的参考值 - */ - private String defaultConfig; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowEngineException.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowEngineException.java deleted file mode 100644 index a41e1b73..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowEngineException.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.exception; - -import com.qqchen.deploy.backend.framework.exception.BusinessException; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; - -public class WorkflowEngineException extends BusinessException { - - public WorkflowEngineException(ResponseCode code) { - super(code); - } - - public WorkflowEngineException(ResponseCode code, String... args) { - super(code, args); - } - - public WorkflowEngineException(ResponseCode code, Throwable cause) { - super(code, new Object[]{cause.getMessage()}); - } -} \ No newline at end of file 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 deleted file mode 100644 index 4fa928e0..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowNodeException.java +++ /dev/null @@ -1,28 +0,0 @@ -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/executor/AbstractNodeExecutor.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/AbstractNodeExecutor.java deleted file mode 100644 index 17838f6e..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/AbstractNodeExecutor.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.system.enums.LogLevelEnum; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.model.NodeConfig; -import com.qqchen.deploy.backend.workflow.engine.model.WorkflowGraph; -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import com.qqchen.deploy.backend.workflow.repository.INodeInstanceRepository; -import com.qqchen.deploy.backend.workflow.service.IWorkflowLogService; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; - - -/** - * 抽象节点执行器 - */ -@Slf4j -public abstract class AbstractNodeExecutor implements INodeExecutor { - - @Resource - protected ObjectMapper objectMapper; - - @Resource - protected INodeInstanceRepository nodeInstanceRepository; - - @Resource - protected IWorkflowLogService workflowLogService; - - @Resource - @Lazy - private Map nodeExecutors; - - @Override - public void execute(WorkflowInstance workflowInstance, WorkflowGraph graph, NodeConfig currentNode) { - NodeInstance nodeInstance = null; - try { - nodeInstance = createNodeInstance(workflowInstance, currentNode); - } catch (JsonProcessingException e) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e); - } - try { - // 1. 创建节点实例 - // 1. 前置处理 - beforeExecute(workflowInstance, nodeInstance); - - // 2. 执行节点逻辑 - doExecute(workflowInstance, nodeInstance); - - // 3. 后置处理 - afterExecute(workflowInstance, nodeInstance); - - // 4. 更新节点状态 - updateNodeStatus(nodeInstance, true); - - // 4. 获取并执行下一个节点 - List nextNodes = graph.getNextNodes(currentNode.getNodeId()); - executeNextNodes(workflowInstance, graph, nextNodes); - - } catch (Exception e) { - // 5. 异常处理 - handleExecutionError(workflowInstance, nodeInstance, e); - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e); - } - } - - /** - * 执行后续节点 - */ - protected void executeNextNodes(WorkflowInstance workflowInstance, WorkflowGraph graph, List nextNodes) { - for (NodeConfig nextNode : nextNodes) { - INodeExecutor executor = nodeExecutors.get(nextNode.getType()); - executor.execute(workflowInstance, graph, nextNode); - } - } - - /** - * 创建节点实例 - */ - protected NodeInstance createNodeInstance(WorkflowInstance workflowInstance, NodeConfig config) throws JsonProcessingException { - NodeInstance node = new NodeInstance(); - node.setWorkflowInstance(workflowInstance); - node.setNodeId(config.getNodeId()); - node.setNodeType(config.getType()); - node.setName(config.getName()); - node.setConfig(objectMapper.writeValueAsString(config.getConfig())); - node.setStatus(NodeStatusEnum.RUNNING); - node.setCreateTime(LocalDateTime.now()); - node.setStartTime(LocalDateTime.now()); - return nodeInstanceRepository.save(node); - } - - /** - * 执行节点逻辑 - */ - protected abstract void doExecute(WorkflowInstance workflowInstance, NodeInstance nodeInstance); - - /** - * 前置处理 - */ - protected void beforeExecute(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { - } - - /** - * 后置处理 - */ - protected void afterExecute(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { - logNodeComplete(nodeInstance); - } - - /** - * 处理执行异常 - */ - protected void handleExecutionError(WorkflowInstance workflowInstance, NodeInstance nodeInstance, Exception e) { - log.error("Node execution failed. nodeInstance: {}, error: {}", nodeInstance.getId(), e.getMessage(), e); - logSystem(nodeInstance, LogLevelEnum.ERROR, String.format("节点执行失败: %s[%s]", nodeInstance.getName(), nodeInstance.getNodeId()), e.getMessage()); - logNodeError(nodeInstance, e.getMessage()); - updateNodeStatus(nodeInstance, false); - } - - /** - * 更新节点状态 - */ - private void updateNodeStatus(NodeInstance nodeInstance, boolean success) { - nodeInstance.setStatus(success ? NodeStatusEnum.COMPLETED : NodeStatusEnum.FAILED); - if (success) { - nodeInstance.setEndTime(LocalDateTime.now()); - } - nodeInstanceRepository.save(nodeInstance); - } - - /** - * 记录系统日志 - */ - protected void logSystem(NodeInstance nodeInstance, LogLevelEnum level, String message, String detail) { - workflowLogService.log(nodeInstance.getWorkflowInstance(), nodeInstance.getNodeId(), level, message, detail); - } - - - /** - * 记录节点完成日志 - */ - protected void logNodeComplete(NodeInstance nodeInstance) { - workflowLogService.log(nodeInstance.getWorkflowInstance(), nodeInstance.getNodeId(), LogLevelEnum.INFO, String.format("节点执行完成: %s", nodeInstance.getName()), null); - } - - /** - * 记录节点错误日志 - */ - protected void logNodeError(NodeInstance nodeInstance, String error) { - workflowLogService.log(nodeInstance.getWorkflowInstance(), nodeInstance.getNodeId(), LogLevelEnum.ERROR, String.format("节点执行失败: %s", nodeInstance.getName()), error); - nodeInstance.setError(error); - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/EndNodeExecutor.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/EndNodeExecutor.java deleted file mode 100644 index 6e790c86..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/EndNodeExecutor.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor; - -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - - -/** - * 结束节点执行器 - * 负责完成工作流实例的执行 - */ -@Slf4j -@Component("endNodeExecutor") -public class EndNodeExecutor extends AbstractNodeExecutor { - - - @Override - protected void doExecute(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { - - } - - @Override - public NodeTypeEnum getNodeType() { - return NodeTypeEnum.END; - } - - @Override - public void validate(String config) { - - } - - @Override - public void terminate(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { - - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/INodeExecutor.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/INodeExecutor.java deleted file mode 100644 index 1d38c659..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/INodeExecutor.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor; - -import com.qqchen.deploy.backend.workflow.engine.model.NodeConfig; -import com.qqchen.deploy.backend.workflow.engine.model.WorkflowGraph; -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; - -/** - * 节点执行器接口 - */ -public interface INodeExecutor { - - /** - * 获取支持的节点类型 - */ - NodeTypeEnum getNodeType(); - - void execute(WorkflowInstance workflowInstance, WorkflowGraph graph, NodeConfig currentNode); - - /** - * 验证节点配置 - */ - void validate(String config); - - void terminate(WorkflowInstance workflowInstance, NodeInstance nodeInstance); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/ScriptNodeExecutor.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/ScriptNodeExecutor.java deleted file mode 100644 index 8bd07b29..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/ScriptNodeExecutor.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor; - -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -/** - * 脚本节点执行器 - * 支持多种脚本语言(Python, Shell, JavaScript等) - */ -@Slf4j -@Component("scriptNodeExecutor") -public class ScriptNodeExecutor extends AbstractNodeExecutor { - - @Override - protected void doExecute(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { - - } - - @Override - public NodeTypeEnum getNodeType() { - return NodeTypeEnum.SCRIPT; - } - - @Override - public void validate(String config) { - - } - - @Override - public void terminate(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { - - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/StartNodeExecutor.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/StartNodeExecutor.java deleted file mode 100644 index 546a8e5e..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/StartNodeExecutor.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor; - -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -/** - * 开始节点执行器 - * 负责工作流实例的初始化工作 - */ -@Slf4j -@Component("startNodeExecutor") -public class StartNodeExecutor extends AbstractNodeExecutor { - - - @Override - protected void doExecute(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { - - } - - @Override - public NodeTypeEnum getNodeType() { - return NodeTypeEnum.START; - } - - @Override - public void validate(String config) { - - } - - @Override - public void terminate(WorkflowInstance workflowInstance, NodeInstance nodeInstance) { - - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ApprovalNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ApprovalNodeExecutorConfig.java deleted file mode 100644 index a2fb5057..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ApprovalNodeExecutorConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -/** - * 审批节点配置 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class ApprovalNodeExecutorConfig extends NodeExecutorConfig { - - /** - * 审批人类型:USER-指定用户,ROLE-指定角色,LEADER-直属领导 - */ - private String approverType; - - /** - * 审批人ID列表(用户ID或角色ID) - */ - private List approverIds; - - /** - * 审批策略:ALL-全部通过,ANY-任意通过 - */ - private String strategy; - - /** - * 审批超时自动处理:PASS-通过,REJECT-拒绝 - */ - private String timeoutAction; - - /** - * 审批表单定义 - */ - private String formDefinition; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ConditionNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ConditionNodeExecutorConfig.java deleted file mode 100644 index bc0c5765..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ConditionNodeExecutorConfig.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import java.util.List; - -/** - * 条件节点配置 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class ConditionNodeExecutorConfig extends NodeExecutorConfig { - - /** - * 条件表达式(使用SpEL表达式) - */ - private String expression; - - /** - * 条件分支列表 - */ - private List branches; - - /** - * 默认分支节点ID - */ - private String defaultBranchNodeId; - - @Data - public static class Branch { - /** - * 分支名称 - */ - private String name; - - /** - * 条件表达式 - */ - private String condition; - - /** - * 下一个节点ID - */ - private String nextNodeId; - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/GitNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/GitNodeExecutorConfig.java deleted file mode 100644 index 531b8454..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/GitNodeExecutorConfig.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * Git节点配置 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class GitNodeExecutorConfig extends NodeExecutorConfig { - - /** - * Git仓库URL - */ - private String repositoryUrl; - - /** - * 分支名称 - */ - private String branch; - - /** - * 标签名称 - */ - private String tag; - - /** - * Commit ID - */ - private String commitId; - - /** - * 操作类型:CLONE, PULL, PUSH, TAG, MERGE - */ - private String operation; - - /** - * 目标分支(合并时使用) - */ - private String targetBranch; - - /** - * 工作目录 - */ - private String workingDirectory; - - /** - * 凭证ID - */ - private Long credentialId; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/HttpNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/HttpNodeExecutorConfig.java deleted file mode 100644 index a72f8d03..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/HttpNodeExecutorConfig.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import java.util.Map; - -/** - * HTTP节点配置 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class HttpNodeExecutorConfig extends NodeExecutorConfig { - - /** - * 请求URL - */ - private String url; - - /** - * 请求方法:GET, POST, PUT, DELETE - */ - private String method; - - /** - * 请求头 - */ - private Map headers; - - /** - * 请求参数 - */ - private Map parameters; - - /** - * 请求体 - */ - private String body; - - /** - * 请求体格式:JSON, XML, FORM - */ - private String bodyFormat; - - /** - * 成功状态码 - */ - private Integer successCode; - - /** - * 成功响应匹配规则(JSON Path表达式) - */ - private String successResponse; - - /** - * 凭证ID - */ - private Long credentialId; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/JenkinsNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/JenkinsNodeExecutorConfig.java deleted file mode 100644 index be92b9f0..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/JenkinsNodeExecutorConfig.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import java.util.Map; - -/** - * Jenkins节点配置 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class JenkinsNodeExecutorConfig extends NodeExecutorConfig { - - /** - * Jenkins服务器ID - */ - private Long jenkinsServerId; - - /** - * Jenkins任务名称 - */ - private String jobName; - - /** - * 构建参数 - */ - private Map parameters; - - /** - * 等待构建完成 - */ - private Boolean waitForComplete; - - /** - * 构建超时时间(分钟) - */ - private Integer buildTimeout; - - /** - * 构建成功条件:BUILD_RESULT-构建结果,TEST_RESULT-测试结果,QUALITY_GATE-质量门禁 - */ - private String successCondition; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NacosNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NacosNodeExecutorConfig.java deleted file mode 100644 index 336f877b..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NacosNodeExecutorConfig.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import java.util.Map; - -/** - * Nacos节点配置 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class NacosNodeExecutorConfig extends NodeExecutorConfig { - - /** - * Nacos服务器ID - */ - private Long nacosServerId; - - /** - * 命名空间 - */ - private String namespace; - - /** - * 分组 - */ - private String group; - - /** - * 数据ID - */ - private String dataId; - - /** - * 操作类型:PUBLISH-发布配置,ROLLBACK-回滚配置 - */ - private String operation; - - /** - * 配置内容 - */ - private String content; - - /** - * 配置格式:TEXT, JSON, XML, YAML, PROPERTIES - */ - private String format; - - /** - * 回滚版本ID(回滚时使用) - */ - private Long historyId; - - /** - * 标签列表 - */ - private Map tags; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NodeExecutorConfig.java deleted file mode 100644 index f7484750..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NodeExecutorConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.Data; - -/** - * 节点配置基类 - */ -public class NodeExecutorConfig { - - /** - * 节点ID - */ - private String id; - - /** - * 节点名称 - */ - private String name; - - /** - * 节点类型 - */ - private NodeTypeEnum type; - - /** - * 描述 - */ - private String description; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NotifyNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NotifyNodeExecutorConfig.java deleted file mode 100644 index b3b1ad45..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/NotifyNodeExecutorConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import java.util.List; -import java.util.Map; - -/** - * 通知节点配置 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class NotifyNodeExecutorConfig extends NodeExecutorConfig { - - /** - * 通知类型:EMAIL-邮件,SMS-短信,DINGTALK-钉钉,WEIXIN-企业微信 - */ - private String notifyType; - - /** - * 通知人类型:USER-指定用户,ROLE-指定角色,LEADER-直属领导 - */ - private String receiverType; - - /** - * 通知人ID列表(用户ID或角色ID) - */ - private List receiverIds; - - /** - * 通知标题 - */ - private String title; - - /** - * 通知内容 - */ - private String content; - - /** - * 通知模板ID - */ - private Long templateId; - - /** - * 模板参数 - */ - private Map templateParams; - - /** - * 附件列表 - */ - private List attachments; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ParallelNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ParallelNodeExecutorConfig.java deleted file mode 100644 index 3c30345a..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ParallelNodeExecutorConfig.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import java.util.List; - -/** - * 并行节点配置 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class ParallelNodeExecutorConfig extends NodeExecutorConfig { - - /** - * 并行分支列表 - */ - private List branches; - - /** - * 汇聚策略:ALL-全部完成,ANY-任一完成,N-N个完成 - */ - private String joinStrategy; - - /** - * 需要完成的分支数量(N个完成时使用) - */ - private Integer requiredCount; - - /** - * 下一个节点ID - */ - private String nextNodeId; - - @Data - public static class Branch { - /** - * 分支名称 - */ - private String name; - - /** - * 起始节点ID - */ - private String startNodeId; - - /** - * 结束节点ID - */ - private String endNodeId; - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ScriptNodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ScriptNodeExecutorConfig.java deleted file mode 100644 index 6f128d2f..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/config/ScriptNodeExecutorConfig.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.config; - -import com.qqchen.deploy.backend.workflow.enums.ScriptLanguageEnum; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.Map; - -/** - * 脚本节点配置 - * 支持多种脚本语言(Python, Shell, JavaScript等) - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class ScriptNodeExecutorConfig extends NodeExecutorConfig { - /** - * 脚本内容 - */ - private String script; - - /** - * 脚本语言:python/shell/javascript - */ - private ScriptLanguageEnum language; - - /** - * 解释器路径(可选) - * 例如:/usr/local/bin/python3 - */ - private String interpreter; - - /** - * 工作目录 - */ - private String workingDirectory; - - /** - * 超时时间(秒) - */ - private Integer timeout; - - /** - * 重试次数 - */ - private Integer retryTimes; - - /** - * 重试间隔(秒) - */ - private Integer retryInterval; - - /** - * 环境变量 - */ - private Map environment; - - /** - * 成功退出码 - */ - private Integer successExitCode = 0; - - /** - * 失败是否继续 - */ - private Boolean continueOnFailed; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/NodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/NodeConfig.java deleted file mode 100644 index 2a7c5da6..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/NodeConfig.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.model; - -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.Data; - -import java.util.Map; - -/** - * 节点配置 - * 用于解析工作流定义中的节点配置JSON - */ -@Data -public class NodeConfig { - /** - * 节点ID - */ - private String nodeId; - - /** - * 节点类型 - */ - private NodeTypeEnum type; - - /** - * 节点名称 - */ - private String name; - - /** - * 节点配置,不同类型的节点有不同的配置项 - */ - private Map config; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/TransitionConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/TransitionConfig.java deleted file mode 100644 index 1349b58a..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/TransitionConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.model; - -import lombok.Data; - -/** - * 流转配置 - * 用于解析工作流定义中的流转配置JSON - */ -@Data -public class TransitionConfig { - /** - * 来源节点ID - */ - private String from; - - /** - * 目标节点ID - */ - private String to; - - /** - * 流转条件 - */ - private String condition; - - /** - * 流转描述 - */ - private String description; - - /** - * 优先级,数字越小优先级越高 - */ - private Integer priority; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/WorkflowGraph.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/WorkflowGraph.java deleted file mode 100644 index bb3e52bd..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/model/WorkflowGraph.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.model; - -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.Builder; -import lombok.Data; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -@Data -@Builder -public class WorkflowGraph { - - private List nodes; - - private List transitions; - - public NodeConfig getStartNode() { - return nodes.stream() - .filter(node -> node.getType() == NodeTypeEnum.START) - .findFirst() - .orElseThrow(() -> new WorkflowEngineException(ResponseCode.WORKFLOW_NOT_FOUND)); - } - - public List getNextNodes(String nodeId) { - return transitions.stream() - .filter(t -> t.getFrom().equals(nodeId)) - .map(t -> findNodeById(t.getTo())) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - private NodeConfig findNodeById(String nodeId) { - return nodes.stream() - .filter(n -> n.getNodeId().equals(nodeId)) - .findFirst() - .orElse(null); - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/parser/WorkflowDefinitionParser.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/parser/WorkflowDefinitionParser.java deleted file mode 100644 index 9eed5a23..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/parser/WorkflowDefinitionParser.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.parser; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.model.NodeConfig; -import com.qqchen.deploy.backend.workflow.engine.model.TransitionConfig; -import com.qqchen.deploy.backend.workflow.engine.model.WorkflowGraph; -import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * 工作流定义解析器 - */ -@Component -@Slf4j -public class WorkflowDefinitionParser { - private final ObjectMapper objectMapper; - - public WorkflowDefinitionParser(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } - - public WorkflowGraph parse(WorkflowDefinition definition) { - try { - // 解析节点配置 - JsonNode rootNode = objectMapper.readTree(definition.getNodeConfig()); - List nodes = parseNodes(rootNode.get("nodes")); - - // 解析流转配置 - JsonNode transitionRoot = objectMapper.readTree(definition.getTransitionConfig()); - List transitions = parseTransitions(transitionRoot.get("transitions")); - - return WorkflowGraph.builder() - .nodes(nodes) - .transitions(transitions) - .build(); - - } catch (Exception e) { - log.error("Failed to parse workflow definition", e); - throw new WorkflowEngineException(ResponseCode.WORKFLOW_CONFIG_ERROR); - } - } - - private List parseNodes(JsonNode nodesNode) { - List nodes = new ArrayList<>(); - for (JsonNode node : nodesNode) { - NodeConfig config = new NodeConfig(); - config.setNodeId(node.get("id").asText()); - config.setType(NodeTypeEnum.valueOf(node.get("type").asText())); - config.setName(node.get("name").asText()); - config.setConfig(objectMapper.convertValue(node.get("config"), new TypeReference>() {})); - nodes.add(config); - } - return nodes; - } - - private List parseTransitions(JsonNode transitionsNode) { - List transitions = new ArrayList<>(); - for (JsonNode transition : transitionsNode) { - TransitionConfig config = new TransitionConfig(); - config.setFrom(transition.get("from").asText()); - config.setTo(transition.get("to").asText()); - config.setCondition(transition.get("condition").asText()); - config.setPriority(transition.get("priority").asInt()); - transitions.add(config); - } - return transitions; - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/ScriptCommand.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/ScriptCommand.java deleted file mode 100644 index 3fbcbe9b..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/ScriptCommand.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.script.command; - -import com.qqchen.deploy.backend.workflow.engine.executor.config.ScriptNodeExecutorConfig; - -import java.util.List; - -/** - * 脚本命令构建接口 - */ -public interface ScriptCommand { - /** - * 构建脚本执行命令 - * @param config 脚本配置 - * @return 命令行参数列表 - */ - List buildCommand(ScriptNodeExecutorConfig config); -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/ScriptLanguageSupport.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/ScriptLanguageSupport.java deleted file mode 100644 index 54d52f28..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/ScriptLanguageSupport.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.script.command; - -import com.qqchen.deploy.backend.workflow.enums.ScriptLanguageEnum; -import java.lang.annotation.*; - -/** - * 脚本语言支持注解 - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface ScriptLanguageSupport { - /** - * 支持的脚本语言类型 - */ - ScriptLanguageEnum value(); -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/impl/PythonScriptCommand.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/impl/PythonScriptCommand.java deleted file mode 100644 index 9c7d22c6..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/impl/PythonScriptCommand.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.script.command.impl; - -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.executor.config.ScriptNodeExecutorConfig; -import com.qqchen.deploy.backend.workflow.engine.script.command.ScriptCommand; -import com.qqchen.deploy.backend.workflow.engine.script.command.ScriptLanguageSupport; -import com.qqchen.deploy.backend.workflow.enums.ScriptLanguageEnum; -import org.springframework.stereotype.Component; -import java.util.Arrays; -import java.util.List; - -/** - * Python脚本命令构建实现 - */ -@Component -@ScriptLanguageSupport(ScriptLanguageEnum.PYTHON) -public class PythonScriptCommand implements ScriptCommand { - @Override - public List buildCommand(ScriptNodeExecutorConfig config) { - if (config.getInterpreter() == null || config.getInterpreter().trim().isEmpty()) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, - "Python interpreter path must be specified"); - } - return Arrays.asList( - config.getInterpreter(), - "-c", - config.getScript() - ); - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/impl/ShellScriptCommand.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/impl/ShellScriptCommand.java deleted file mode 100644 index 071ff003..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/command/impl/ShellScriptCommand.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.script.command.impl; - -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.executor.config.ScriptNodeExecutorConfig; -import com.qqchen.deploy.backend.workflow.engine.script.command.ScriptCommand; -import com.qqchen.deploy.backend.workflow.engine.script.command.ScriptLanguageSupport; -import com.qqchen.deploy.backend.workflow.enums.ScriptLanguageEnum; -import org.springframework.stereotype.Component; -import java.util.Arrays; -import java.util.List; - -/** - * Shell脚本命令构建实现 - */ -@Component -@ScriptLanguageSupport(ScriptLanguageEnum.SHELL) -public class ShellScriptCommand implements ScriptCommand { - @Override - public List buildCommand(ScriptNodeExecutorConfig config) { - if (config.getInterpreter() == null || config.getInterpreter().trim().isEmpty()) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, - "Shell interpreter path must be specified"); - } - return Arrays.asList( - config.getInterpreter(), - "-c", - config.getScript() - ); - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/registry/ScriptCommandRegistry.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/registry/ScriptCommandRegistry.java deleted file mode 100644 index 40cf9f60..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/script/registry/ScriptCommandRegistry.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.script.registry; - -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.script.command.ScriptCommand; -import com.qqchen.deploy.backend.workflow.engine.script.command.ScriptLanguageSupport; -import com.qqchen.deploy.backend.workflow.enums.ScriptLanguageEnum; -import jakarta.annotation.PostConstruct; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 脚本命令注册表 - */ -@Component -public class ScriptCommandRegistry { - private final Map commands = new ConcurrentHashMap<>(); - - @Autowired - private List scriptCommands; - - @PostConstruct - public void init() { - scriptCommands.forEach(command -> { - ScriptLanguageSupport support = command.getClass().getAnnotation(ScriptLanguageSupport.class); - if (support != null) { - registerCommand(support.value(), command); - } - }); - } - - /** - * 注册脚本命令实现 - * @param language 脚本语言 - * @param command 命令实现 - */ - public void registerCommand(ScriptLanguageEnum language, ScriptCommand command) { - commands.put(language, command); - } - - /** - * 获取脚本命令实现 - * @param language 脚本语言 - * @return 命令实现 - */ - public ScriptCommand getCommand(ScriptLanguageEnum language) { - ScriptCommand command = commands.get(language); - if (command == null) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, - "No command implementation found for language: " + language.getDescription()); - } - return command; - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeInstance.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeInstance.java deleted file mode 100644 index 6fe2d51a..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeInstance.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.qqchen.deploy.backend.workflow.entity; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.qqchen.deploy.backend.framework.annotation.LogicDelete; -import com.qqchen.deploy.backend.framework.domain.Entity; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.framework.utils.SpringUtils; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.executor.config.NodeExecutorConfig; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import jakarta.persistence.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDateTime; - -/** - * - */ -@Data -@EqualsAndHashCode(callSuper = true) -@jakarta.persistence.Entity -@Table(name = "wf_node_instance") -@LogicDelete -public class NodeInstance extends Entity { - - /** - * - */ - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "workflow_instance_id", nullable = false) - private WorkflowInstance workflowInstance; - - /** - * ID - */ - @Column(nullable = false) - private String nodeId; - - /** - * - */ - @Enumerated(EnumType.ORDINAL) - @Column(nullable = false) - private NodeTypeEnum nodeType; - - /** - * - */ - @Column(nullable = false) - private String name; - - /** - * - */ - @Enumerated(EnumType.ORDINAL) - @Column(nullable = false) - private NodeStatusEnum status; - - /** - * - */ - private LocalDateTime startTime; - - /** - * - */ - private LocalDateTime endTime; - - /** - * (JSON) - */ - @Column(columnDefinition = "TEXT") - private String config; - - /** - * (JSON) - */ - @Column(columnDefinition = "TEXT") - private String input; - - /** - * (JSON) - */ - @Column(columnDefinition = "TEXT") - private String output; - - /** - * - */ - @Column(columnDefinition = "TEXT") - private String error; - - /** - * ID - */ - private String preNodeId; - - @Transient - private NodeExecutorConfig configObject; - - private static ObjectMapper getObjectMapper() { - return SpringUtils.getBean(ObjectMapper.class); - } - - public String getConfig() { - return config; - } - - public String getPreNodeId() { - return preNodeId; - } - - public T getConfigObject(Class configClass) { - if (configObject == null && config != null) { - try { - configObject = getObjectMapper().readValue(this.config, configClass); - } catch (Exception e) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, - String.format("Failed to parse config for node %s: %s", name, e.getMessage())); - } - } - return (T) configObject; - } - - public void setConfigObject(NodeExecutorConfig config) { - this.configObject = config; - try { - this.config = getObjectMapper().writeValueAsString(config); - } catch (Exception e) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, - String.format("Failed to serialize config for node %s: %s", name, e.getMessage())); - } - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeType.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeType.java deleted file mode 100644 index 1c1d0374..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeType.java +++ /dev/null @@ -1,81 +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.NodeCategoryEnum; -import jakarta.persistence.Column; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.Table; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 节点类型实体 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@jakarta.persistence.Entity -@Table(name = "wf_node_type") -@LogicDelete -public class NodeType extends Entity { - - /** - * 节点类型编码 - */ - @Column(nullable = false, unique = true) - private String code; - - /** - * 节点类型名称 - */ - @Column(nullable = false) - private String name; - - /** - * 节点类型描述 - */ - @Column(columnDefinition = "TEXT") - private String description; - - /** - * 节点类型分类 - */ - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private NodeCategoryEnum category; - - /** - * 节点图标 - */ - private String icon; - - /** - * 节点颜色 - */ - private String color; - - /** - * 执行器列表(JSON) - */ - @Column(name = "executors", columnDefinition = "TEXT") - private String executors; - - /** - * 节点配置模式(JSON) - */ - @Column(name = "config_schema", columnDefinition = "TEXT") - private String configSchema; - - /** - * 默认配置(JSON) - */ - @Column(name = "default_config", columnDefinition = "TEXT") - private String defaultConfig; - - /** - * 是否启用 - */ - @Column(nullable = false) - private Boolean enabled = true; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowDefinition.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowDefinition.java index cd9dd771..bfbd6343 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowDefinition.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowDefinition.java @@ -1,161 +1,52 @@ 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.WorkflowDefinitionStatusEnum; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import java.util.ArrayList; -import java.util.List; - /** * 工作流定义实体 */ @Data -@EqualsAndHashCode(callSuper = true) +@Table(name = "workflow_definition") @jakarta.persistence.Entity -@Table(name = "wf_workflow_definition") -@LogicDelete +@EqualsAndHashCode(callSuper = true) public class WorkflowDefinition extends Entity { - + /** - * 工作流编码,唯一标识 - */ - @Column(nullable = false, unique = true) - private String code; - - /** - * 工作流名称 + * 流程名称 */ @Column(nullable = false) private String name; - + /** - * 工作流描述 + * 流程标识 + */ + @Column(nullable = false) + private String key; + + /** + * 流程版本 + */ + @Column(nullable = false) + private Integer version; + + /** + * BPMN XML内容 + */ + @Column(name = "bpmn_xml", columnDefinition = "TEXT") + private String bpmnXml; + + /** + * 流程图JSON数据 + */ + @Column(name = "graph_json", columnDefinition = "TEXT") + private String graphJson; + + /** + * 流程描述 */ - @Column(columnDefinition = "TEXT") private String description; - - /** - * 工作流状态 - */ - @Enumerated(EnumType.ORDINAL) - @Column(nullable = false) - private WorkflowDefinitionStatusEnum status = WorkflowDefinitionStatusEnum.DRAFT; - - /** - * 是否启用 - */ - @Column(nullable = false) - private Boolean enabled = true; - - /** - * 节点配置(JSON) - */ - @Column(name = "node_config", columnDefinition = "TEXT") - private String nodeConfig; - - /** - * 流转配置(JSON) - */ - @Column(name = "transition_config", columnDefinition = "TEXT") - private String transitionConfig; - - /** - * 表单定义(JSON) - */ - @Column(name = "form_definition", columnDefinition = "TEXT") - private String formDefinition; - - /** - * 图形信息(JSON) - */ - @Column(name = "graph_definition", columnDefinition = "TEXT") - private String graphDefinition; - - /** - * 版本号 - */ - @Column(nullable = false) - private Integer version = 1; - - /** - * 获取流转配置 - */ - public String getTransitionConfig() { - return transitionConfig; - } - - /** - * 检查是否可以发布 - */ - public boolean canPublish() { - return status == WorkflowDefinitionStatusEnum.DRAFT; - } - - /** - * 检查是否可以禁用 - */ - public boolean canDisable() { - return status == WorkflowDefinitionStatusEnum.PUBLISHED; - } - - /** - * 检查是否可以启用 - */ - public boolean canEnable() { - return status == WorkflowDefinitionStatusEnum.DISABLED; - } - - /** - * 检查是否可以更新 - */ - public boolean canUpdate() { - return status == WorkflowDefinitionStatusEnum.DRAFT; - } - - /** - * 发布工作流定义 - */ - public void publish() { - if (!canPublish()) { - throw new IllegalStateException("Cannot publish workflow definition in " + status + " status"); - } - this.status = WorkflowDefinitionStatusEnum.PUBLISHED; - } - - /** - * 禁用工作流定义 - */ - public void disable() { - if (!canDisable()) { - throw new IllegalStateException("Cannot disable workflow definition in " + status + " status"); - } - this.status = WorkflowDefinitionStatusEnum.DISABLED; - } - - /** - * 启用工作流定义 - */ - public void enable() { - if (!canEnable()) { - throw new IllegalStateException("Cannot enable workflow definition in " + status + " status"); - } - this.status = WorkflowDefinitionStatusEnum.PUBLISHED; - } - - /** - * 创建新版本 - */ - public WorkflowDefinition createNewVersion() { - WorkflowDefinition newVersion = new WorkflowDefinition(); - newVersion.setCode(this.code); - newVersion.setName(this.name); - newVersion.setDescription(this.description); - newVersion.setVersion(this.version + 1); - newVersion.setStatus(WorkflowDefinitionStatusEnum.DRAFT); - return newVersion; - } -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowInstance.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowInstance.java index 198f0a30..2e8bc4f3 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowInstance.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowInstance.java @@ -1,239 +1,61 @@ 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.WorkflowInstanceStatusEnum; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; + import java.time.LocalDateTime; /** * 工作流实例实体 */ @Data -@EqualsAndHashCode(callSuper = true) +@Table(name = "workflow_instance") @jakarta.persistence.Entity -@Table(name = "wf_workflow_instance") -@LogicDelete +@EqualsAndHashCode(callSuper = true) public class WorkflowInstance extends Entity { - + /** - * 工作流定义 + * 流程实例ID */ - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "workflow_definition_id", nullable = false) - private WorkflowDefinition workflowDefinition; - + @Column(name = "process_instance_id", nullable = false) + private String processInstanceId; + /** - * 工作流定义ID,用于查询优化 + * 流程定义ID */ - @Column(name = "workflow_definition_id", insertable = false, updatable = false) - private Long workflowDefinitionId; - - /** - * 项目环境ID - */ - @Column(name = "project_env_id") - private Long projectEnvId; - + @Column(name = "process_definition_id", nullable = false) + private Long processDefinitionId; + /** * 业务标识 */ - @Column(name = "business_key", nullable = false) + @Column(name = "business_key") private String businessKey; - + /** - * 工作流状态 + * 实例状态 */ - @Enumerated(EnumType.ORDINAL) @Column(nullable = false) - private WorkflowInstanceStatusEnum status = WorkflowInstanceStatusEnum.CREATED; - + private String status; + + /** + * 流程变量(JSON) + */ + @Column(columnDefinition = "TEXT") + private String variables; + /** * 开始时间 */ - @Column(name = "start_time") + @Column(name = "start_time", nullable = false) private LocalDateTime startTime; - + /** * 结束时间 */ @Column(name = "end_time") private LocalDateTime endTime; - - /** - * 错误信息 - */ - @Column(columnDefinition = "TEXT") - private String error; - - /** - * 设置工作流定义 - */ - public void setDefinition(WorkflowDefinition definition) { - this.workflowDefinition = definition; - } - - /** - * 检查是否可以启动 - */ - public boolean canStart() { - return status == WorkflowInstanceStatusEnum.CREATED || status == WorkflowInstanceStatusEnum.PENDING; - } - - /** - * 检查是否可以暂停 - */ - public boolean canPause() { - return status == WorkflowInstanceStatusEnum.RUNNING; - } - - /** - * 检查是否可以恢复 - */ - public boolean canResume() { - return status == WorkflowInstanceStatusEnum.PAUSED; - } - - /** - * 检查是否可以终止 - */ - public boolean canTerminate() { - return status == WorkflowInstanceStatusEnum.RUNNING || - status == WorkflowInstanceStatusEnum.PAUSED; - } - - /** - * 检查是否可以完成 - */ - public boolean canComplete() { - return status == WorkflowInstanceStatusEnum.RUNNING; - } - - /** - * 检查是否可以执行节点 - */ - public boolean canExecuteNode() { - return status == WorkflowInstanceStatusEnum.RUNNING; - } - - /** - * 启动工作流实例 - */ - public void start() { - if (!canStart()) { - throw new IllegalStateException("Cannot start workflow instance in " + status + " status"); - } - this.status = WorkflowInstanceStatusEnum.RUNNING; - this.startTime = LocalDateTime.now(); - } - - /** - * 暂停工作流实例 - */ - public void pause() { - if (!canPause()) { - throw new IllegalStateException("Cannot pause workflow instance in " + status + " status"); - } - this.status = WorkflowInstanceStatusEnum.PAUSED; - } - - /** - * 恢复工作流实例 - */ - public void resume() { - if (!canResume()) { - throw new IllegalStateException("Cannot resume workflow instance in " + status + " status"); - } - this.status = WorkflowInstanceStatusEnum.RUNNING; - } - - /** - * 终止工作流实例 - */ - public void terminate(String reason) { - if (!canTerminate()) { - throw new IllegalStateException("Cannot terminate workflow instance in " + status + " status"); - } - this.status = WorkflowInstanceStatusEnum.TERMINATED; - this.endTime = LocalDateTime.now(); - this.error = reason; - } - - - /** - * 标记工作流实例为失败 - */ - public void fail(String error) { - this.status = WorkflowInstanceStatusEnum.FAILED; - this.endTime = LocalDateTime.now(); - this.error = error; - } - - /** - * 检查工作流实例是否处于活动状态 - */ - public boolean isActive() { - return status == WorkflowInstanceStatusEnum.RUNNING || - status == WorkflowInstanceStatusEnum.PENDING || - status == WorkflowInstanceStatusEnum.PAUSED; - } - - /** - * 检查工作流实例是否已经结束 - */ - public boolean isEnded() { - return status == WorkflowInstanceStatusEnum.COMPLETED || - status == WorkflowInstanceStatusEnum.TERMINATED || - status == WorkflowInstanceStatusEnum.FAILED; - } - - /** - * 检查工作流实例是否可以重试 - */ - public boolean canRetry() { - return status == WorkflowInstanceStatusEnum.FAILED; - } - - /** - * 重试工作流实例 - */ - public void retry() { - if (!canRetry()) { - throw new IllegalStateException("Cannot retry workflow instance in " + status + " status"); - } - this.status = WorkflowInstanceStatusEnum.PENDING; - this.error = null; - } - - /** - * 获取工作流实例的运行时长(毫秒) - */ - public long getDuration() { - if (startTime == null) { - return 0; - } - LocalDateTime end = endTime != null ? endTime : LocalDateTime.now(); - return java.time.Duration.between(startTime, end).toMillis(); - } - - /** - * 检查工作流实例是否超时 - * @param timeoutMillis 超时时间(毫秒) - */ - public boolean isTimeout(long timeoutMillis) { - return startTime != null && getDuration() > timeoutMillis; - } - - /** - * 更新工作流实例的错误信息 - */ - public void updateError(String error) { - this.error = error; - if (this.status == WorkflowInstanceStatusEnum.RUNNING) { - this.status = WorkflowInstanceStatusEnum.FAILED; - this.endTime = LocalDateTime.now(); - } - } -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowLog.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowLog.java index 510f7d23..d21fa40d 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowLog.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowLog.java @@ -1,12 +1,7 @@ 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.system.enums.LogLevelEnum; import jakarta.persistence.Column; -import jakarta.persistence.FetchType; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; @@ -15,28 +10,38 @@ import lombok.EqualsAndHashCode; * 工作流日志实体 */ @Data -@EqualsAndHashCode(callSuper = true) -@Table(name = "wf_log") -@LogicDelete +@Table(name = "workflow_log") @jakarta.persistence.Entity +@EqualsAndHashCode(callSuper = true) public class WorkflowLog extends Entity { - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "workflow_instance_id", nullable = false) - private WorkflowInstance workflowInstance; - - @Column(name = "node_id") - private String nodeId; - + + /** + * 工作流实例ID + */ + @Column(name = "workflow_instance_id") + private Long workflowInstanceId; + + /** + * 节点实例ID + */ + @Column(name = "node_instance_id") + private Long nodeInstanceId; + + /** + * 日志类型 + */ + @Column(name = "log_type", nullable = false) + private String logType; + /** * 日志级别 */ - @Column(name = "level") - private LogLevelEnum level; - - @Column(name = "message", nullable = false, columnDefinition = "TEXT") - private String message; - - @Column(name = "detail", columnDefinition = "TEXT") - private String detail; -} \ No newline at end of file + @Column(name = "log_level", nullable = false) + private String logLevel; + + /** + * 日志内容 + */ + @Column(columnDefinition = "TEXT", nullable = false) + private String content; +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowNodeInstance.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowNodeInstance.java new file mode 100644 index 00000000..cf10d229 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowNodeInstance.java @@ -0,0 +1,73 @@ +package com.qqchen.deploy.backend.workflow.entity; + +import com.qqchen.deploy.backend.framework.domain.Entity; +import jakarta.persistence.Column; +import jakarta.persistence.Table; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 工作流节点实例实体 + */ +@Data +@Table(name = "workflow_node_instance") +@jakarta.persistence.Entity +@EqualsAndHashCode(callSuper = true) +public class WorkflowNodeInstance extends Entity { + + /** + * 工作流实例ID + */ + @Column(name = "workflow_instance_id", nullable = false) + private Long workflowInstanceId; + + /** + * 节点ID + */ + @Column(name = "node_id", nullable = false) + private String nodeId; + + /** + * 节点名称 + */ + @Column(name = "node_name", nullable = false) + private String nodeName; + + /** + * 节点类型 + */ + @Column(name = "node_type", nullable = false) + private String nodeType; + + /** + * 节点状态 + */ + @Column(nullable = false) + private String status; + + /** + * 开始时间 + */ + @Column(name = "start_time", nullable = false) + private LocalDateTime startTime; + + /** + * 结束时间 + */ + @Column(name = "end_time") + private LocalDateTime endTime; + + /** + * 节点变量(JSON) + */ + @Column(columnDefinition = "TEXT") + private String variables; + + /** + * 错误信息 + */ + @Column(name = "error_message", columnDefinition = "TEXT") + private String errorMessage; +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowVariable.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowVariable.java deleted file mode 100644 index e32ac16a..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowVariable.java +++ /dev/null @@ -1,58 +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.VariableScopeEnum; -import com.qqchen.deploy.backend.workflow.enums.VariableTypeEnum; -import jakarta.persistence.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 工作流变量实体 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@jakarta.persistence.Entity -@Table(name = "wf_workflow_variable") -@LogicDelete -public class WorkflowVariable extends Entity { - - /** - * 工作流实例 - */ - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "workflow_instance_id", nullable = false) - private WorkflowInstance workflowInstance; - - /** - * 变量名称 - */ - @Column(nullable = false) - private String name; - - /** - * 变量值(JSON) - */ - @Column(columnDefinition = "TEXT") - private String value; - - /** - * 变量类型 - */ - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private VariableTypeEnum type; - - /** - * 变量作用域 - */ - @Column(nullable = false) - private String scope = VariableScopeEnum.GLOBAL.name(); - - /** - * 节点ID(scope为NODE时必填) - */ - @Column(name = "node_id") - private String nodeId; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/GatewayTypeEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/GatewayTypeEnum.java deleted file mode 100644 index 0a987fa5..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/GatewayTypeEnum.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum GatewayTypeEnum { - - EXCLUSIVE("EXCLUSIVE", "排他网关"), - PARALLEL("PARALLEL", "并行网关"), - INCLUSIVE("INCLUSIVE", "包容网关"); - - private final String code; - private final String description; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeCategoryEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeCategoryEnum.java deleted file mode 100644 index 8e7522a7..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeCategoryEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.Getter; - -/** - * 节点分类枚举 - */ -@Getter -public enum NodeCategoryEnum { - /** - * 基础节点(如开始、结束节点) - */ - BASIC("基础节点"), - - /** - * 任务节点(如Shell、Jenkins等执行器节点) - */ - TASK("任务节点"), - - /** - * 网关节点(如并行、排他、包容网关) - */ - GATEWAY("网关节点"), - - /** - * 事件节点(如定时器、消息等事件) - */ - EVENT("事件节点"); - - /** - * 分类名称 - */ - private final String name; - - NodeCategoryEnum(String name) { - this.name = name; - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeStatusEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeStatusEnum.java deleted file mode 100644 index 70e69fb4..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeStatusEnum.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 节点状态枚举 - */ -@Getter -@AllArgsConstructor -public enum NodeStatusEnum { - - PENDING("PENDING", "等待执行"), - RUNNING("RUNNING", "执行中"), - PAUSED("PAUSED", "已暂停"), - COMPLETED("COMPLETED", "已完成"), - FAILED("FAILED", "执行失败"), - CANCELLED("CANCELLED", "已取消"), - SKIPPED("SKIPPED", "已跳过"), - SUSPENDED("SUSPENDED", "已暂停"), - TERMINATED("TERMINATED", "已终止"); - - private final String code; - private final String description; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeTypeEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeTypeEnum.java deleted file mode 100644 index 6dd054b8..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/NodeTypeEnum.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 节点类型枚举 - */ -@Getter -@AllArgsConstructor -public enum NodeTypeEnum { - - START(0, "START", "开始节点"), - END(1, "END", "结束节点"), - TASK(2, "TASK", "任务节点"), - GATEWAY(3, "GATEWAY", "网关节点"), - SUB_PROCESS(4, "SUB_PROCESS", "子流程节点"), - SHELL(5, "SHELL", "Shell脚本节点"), - SCRIPT(6, "SCRIPT", "脚本节点"), - APPROVAL(7, "APPROVAL", "审批节点"), - JENKINS(8, "JENKINS", "Jenkins任务节点"), - GIT(9, "GIT", "Git操作节点"), - CONDITION(10, "CONDITION", "条件节点"), - PARALLEL(11, "PARALLEL", "并行节点"), - NACOS(12, "NACOS", "Nacos配置节点"), - HTTP(13, "HTTP", "HTTP请求节点"), - NOTIFY(14, "NOTIFY", "通知节点"); - - private final int value; - private final String code; - private final String description; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/ScriptLanguageEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/ScriptLanguageEnum.java deleted file mode 100644 index 1fd9bdd4..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/ScriptLanguageEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import com.fasterxml.jackson.annotation.JsonValue; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -/** - * 脚本语言类型枚举 - */ -@Getter -@RequiredArgsConstructor -public enum ScriptLanguageEnum { - - SHELL("shell", "Shell脚本"), - PYTHON("python", "Python脚本"), - JAVASCRIPT("javascript", "JavaScript脚本"), - GROOVY("groovy", "Groovy脚本"); - - @JsonValue - private final String code; - private final String description; - - public static ScriptLanguageEnum fromCode(String code) { - for (ScriptLanguageEnum language : values()) { - if (language.getCode().equals(code)) { - return language; - } - } - throw new IllegalArgumentException("Unknown script language code: " + code); - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/TaskTypeEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/TaskTypeEnum.java deleted file mode 100644 index fbe0a246..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/TaskTypeEnum.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum TaskTypeEnum { - - HTTP("HTTP", "HTTP请求"), - JAVA("JAVA", "Java方法"); - - private final String code; - private final String description; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/VariableScopeEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/VariableScopeEnum.java deleted file mode 100644 index d217eb7e..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/VariableScopeEnum.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 变量作用域枚举 - */ -@Getter -@AllArgsConstructor -public enum VariableScopeEnum { - - INSTANCE("INSTANCE", "工作流实例"), - NODE("NODE", "节点实例"), - GLOBAL("GLOBAL", "全局"); - - private final String code; - private final String description; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/VariableTypeEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/VariableTypeEnum.java deleted file mode 100644 index 7348ddf7..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/VariableTypeEnum.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -/** - * 变量类型枚举 - */ -public enum VariableTypeEnum { - STRING("字符串"), - NUMBER("数字"), - BOOLEAN("布尔值"), - OBJECT("对象"), - ARRAY("数组"); - - private final String description; - - VariableTypeEnum(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowDefinitionStatusEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowDefinitionStatusEnum.java deleted file mode 100644 index 534d4d30..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowDefinitionStatusEnum.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 工作流定义状态枚举 - */ -@Getter -@AllArgsConstructor -public enum WorkflowDefinitionStatusEnum { - - DRAFT(0, "DRAFT", "草稿"), - PUBLISHED(1, "PUBLISHED", "已发布"), - DISABLED(2, "DISABLED", "已禁用"); - - private final int value; - private final String code; - private final String description; - - public static WorkflowDefinitionStatusEnum fromValue(int value) { - for (WorkflowDefinitionStatusEnum status : values()) { - if (status.getValue() == value) { - return status; - } - } - throw new IllegalArgumentException("No matching WorkflowDefinitionStatusEnum for value: " + value); - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowInstanceStatusEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowInstanceStatusEnum.java deleted file mode 100644 index 986db199..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowInstanceStatusEnum.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 工作流实例状态枚举 - */ -@Getter -@AllArgsConstructor -public enum WorkflowInstanceStatusEnum { - - CREATED(0, "CREATED", "已创建"), - PENDING(1, "PENDING", "等待执行"), - RUNNING(2, "RUNNING", "执行中"), - COMPLETED(3, "COMPLETED", "已完成"), - FAILED(4, "FAILED", "执行失败"), - CANCELLED(5, "CANCELLED", "已取消"), - PAUSED(6, "PAUSED", "已暂停"), - TERMINATED(7, "TERMINATED", "已终止"); - - private final int value; - private final String code; - private final String description; - - public static WorkflowInstanceStatusEnum fromValue(int value) { - for (WorkflowInstanceStatusEnum status : values()) { - if (status.getValue() == value) { - return status; - } - } - throw new IllegalArgumentException("No matching WorkflowInstanceStatusEnum for value: " + value); - } - - /** - * 判断是否为终态 - */ - public boolean isFinalStatus() { - return this == COMPLETED || this == FAILED || this == CANCELLED || this == TERMINATED; - } - - /** - * 判断是否为运行状态 - */ - public boolean isRunning() { - return this == RUNNING; - } - - /** - * 判断是否可以暂停 - */ - public boolean canPause() { - return this == RUNNING; - } - - /** - * 判断是否可以恢复 - */ - public boolean canResume() { - return this == PAUSED; - } - - /** - * 判断是否可以取消 - */ - public boolean canCancel() { - return this == RUNNING || this == PAUSED || this == PENDING; - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowTypeEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowTypeEnum.java deleted file mode 100644 index c2a97ba5..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowTypeEnum.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 工作流类型枚举 - */ -@Getter -@AllArgsConstructor -public enum WorkflowTypeEnum { - - DEPLOY("DEPLOY", "部署工作流"), - CONFIG_SYNC("CONFIG_SYNC", "配置同步工作流"); - - private final String code; - private final String description; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/NodeInstanceQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/NodeInstanceQuery.java deleted file mode 100644 index 9a4f5c92..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/NodeInstanceQuery.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.qqchen.deploy.backend.workflow.query; - -import com.qqchen.deploy.backend.framework.annotation.QueryField; -import com.qqchen.deploy.backend.framework.enums.QueryType; -import com.qqchen.deploy.backend.framework.query.BaseQuery; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Data -@EqualsAndHashCode(callSuper = true) -public class NodeInstanceQuery extends BaseQuery { - - @QueryField(field = "workflowInstanceId") - private Long workflowInstanceId; - - @QueryField(field = "nodeId") - private String nodeId; - - @QueryField(field = "nodeType") - private NodeTypeEnum nodeType; - - @QueryField(field = "name", type = QueryType.LIKE) - private String name; - - @QueryField(field = "status") - private NodeStatusEnum status; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowDefinitionQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowDefinitionQuery.java index 1506ae2d..3e998a4b 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowDefinitionQuery.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowDefinitionQuery.java @@ -3,23 +3,31 @@ package com.qqchen.deploy.backend.workflow.query; import com.qqchen.deploy.backend.framework.annotation.QueryField; import com.qqchen.deploy.backend.framework.enums.QueryType; import com.qqchen.deploy.backend.framework.query.BaseQuery; -import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum; import lombok.Data; import lombok.EqualsAndHashCode; +/** + * 工作流定义查询对象 + */ @Data @EqualsAndHashCode(callSuper = true) public class WorkflowDefinitionQuery extends BaseQuery { - + + /** + * 流程名称 + */ @QueryField(field = "name", type = QueryType.LIKE) private String name; - - @QueryField(field = "code", type = QueryType.LIKE) - private String code; - + /** - * 工作流状态 + * 流程标识 */ - @QueryField(field = "status") - private WorkflowDefinitionStatusEnum status; -} \ No newline at end of file + @QueryField(field = "key", type = QueryType.EQUAL) + private String key; + + /** + * 流程版本 + */ + @QueryField(field = "version", type = QueryType.EQUAL) + private Integer version; +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowInstanceQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowInstanceQuery.java deleted file mode 100644 index ad6950b7..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowInstanceQuery.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.qqchen.deploy.backend.workflow.query; - -import com.qqchen.deploy.backend.framework.annotation.QueryField; -import com.qqchen.deploy.backend.framework.enums.QueryType; -import com.qqchen.deploy.backend.framework.query.BaseQuery; -import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnum; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Data -@EqualsAndHashCode(callSuper = true) -public class WorkflowInstanceQuery extends BaseQuery { - - @QueryField(field = "businessKey", type = QueryType.LIKE) - private String businessKey; - - @QueryField(field = "definitionId") - private Long definitionId; - - /** - * 工作流状态 - */ - @QueryField(field = "status") - private WorkflowInstanceStatusEnum status; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowLogQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowLogQuery.java deleted file mode 100644 index 7b7b3c92..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/query/WorkflowLogQuery.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.qqchen.deploy.backend.workflow.query; - -import com.qqchen.deploy.backend.system.enums.LogLevelEnum; -import com.qqchen.deploy.backend.framework.annotation.QueryField; -import com.qqchen.deploy.backend.framework.enums.QueryType; -import com.qqchen.deploy.backend.framework.query.BaseQuery; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Data -@EqualsAndHashCode(callSuper = true) -public class WorkflowLogQuery extends BaseQuery { - - @QueryField(field = "workflowInstanceId") - private Long workflowInstanceId; - - @QueryField(field = "nodeId") - private String nodeId; - - @QueryField(field = "level") - private LogLevelEnum level; - - @QueryField(field = "message", type = QueryType.LIKE) - private String message; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeInstanceRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeInstanceRepository.java deleted file mode 100644 index 4119b1c2..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeInstanceRepository.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.qqchen.deploy.backend.workflow.repository; - -import com.qqchen.deploy.backend.framework.repository.IBaseRepository; -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; -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 INodeInstanceRepository extends IBaseRepository { - - /** - * 查询工作流实例的所有节点 - */ - @Query("SELECT n FROM NodeInstance n WHERE n.workflowInstance = :instance AND n.deleted = false ORDER BY n.createTime") - List findByWorkflowInstanceOrderByCreateTime(@Param("instance") WorkflowInstance instance); - - /** - * 根据工作流实例ID查询所有节点 - */ - @Query("SELECT n FROM NodeInstance n WHERE n.workflowInstance.id = :workflowInstanceId AND n.deleted = false ORDER BY n.createTime") - List findByWorkflowInstanceId(@Param("workflowInstanceId") Long workflowInstanceId); - - /** - * 根据工作流实例ID和状态查询节点 - */ - @Query("SELECT n FROM NodeInstance n WHERE n.workflowInstance.id = :workflowInstanceId AND n.status = :status AND n.deleted = false ORDER BY n.createTime") - List findByWorkflowInstanceIdAndStatus( - @Param("workflowInstanceId") Long workflowInstanceId, - @Param("status") NodeStatusEnum status); - - /** - * 查询指定状态的节点实例 - */ - List findByWorkflowInstanceAndStatusAndDeletedFalse(WorkflowInstance instance, NodeStatusEnum status); - - List findByWorkflowInstanceAndStatus(WorkflowInstance instance, NodeStatusEnum status); - - List findByWorkflowInstance(WorkflowInstance instance); - - void deleteByWorkflowInstance(WorkflowInstance instance); - - /** - * 查询不是指定状态的节点实例 - */ - List findByWorkflowInstanceAndStatusNot(WorkflowInstance instance, NodeStatusEnum status); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeTypeRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeTypeRepository.java deleted file mode 100644 index 1749ae58..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/INodeTypeRepository.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.qqchen.deploy.backend.workflow.repository; - -import com.qqchen.deploy.backend.framework.repository.IBaseRepository; -import com.qqchen.deploy.backend.workflow.entity.NodeType; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -/** - * 节点类型仓库接口 - */ -@Repository -public interface INodeTypeRepository extends IBaseRepository { - - /** - * 根据编码查询未删除的节点类型 - * - * @param code 节点类型编码 - * @return 节点类型 - */ - Optional findByCodeAndDeletedFalse(String code); - - /** - * 检查编码是否已存在(排除已删除的) - * - * @param code 节点类型编码 - * @return 是否存在 - */ - boolean existsByCodeAndDeletedFalse(String code); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowDefinitionRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowDefinitionRepository.java index de87d35e..13f8cca5 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowDefinitionRepository.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowDefinitionRepository.java @@ -2,75 +2,20 @@ package com.qqchen.deploy.backend.workflow.repository; import com.qqchen.deploy.backend.framework.repository.IBaseRepository; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.List; -import java.util.Optional; - /** - * 工作流定义仓库接口 + * 工作流定义仓库 */ @Repository public interface IWorkflowDefinitionRepository extends IBaseRepository { - /** - * 根据编码查询最新版本的工作流定义 - * - * @param code 工作流编码 - * @return 工作流定义 + * 根据流程标识和版本查询 */ - @Query("SELECT w FROM WorkflowDefinition w WHERE w.code = :code AND w.deleted = false ORDER BY w.version DESC") - Optional findLatestByCode(@Param("code") String code); - + WorkflowDefinition findByKeyAndVersionAndDeletedFalse(String key, Integer version); + /** - * 根据编码和版本号查询工作流定义 - * - * @param code 工作流编码 - * @param version 版本号 - * @return 工作流定义 + * 检查流程标识是否存在 */ - Optional findByCodeAndVersionAndDeletedFalse(String code, Integer version); - - /** - * 根据编码查询所有版本的工作流定义 - * - * @param code 工作流编码 - * @return 工作流定义列表 - */ - @Query("SELECT w FROM WorkflowDefinition w WHERE w.code = :code AND w.deleted = false ORDER BY w.version DESC") - List findAllVersionsByCode(@Param("code") String code); - - /** - * 查询指定状态的工作流定义 - */ - @Query("SELECT d FROM WorkflowDefinition d WHERE d.status = :status AND d.deleted = false") - List findByStatus(@Param("status") WorkflowDefinitionStatusEnum status); - - /** - * 检查编码是否已存在 - * - * @param code 工作流编码 - * @return 是否存在 - */ - boolean existsByCodeAndDeletedFalse(String code); - - /** - * 获取工作流定义的最新版本号 - * - * @param code 工作流编码 - * @return 最新版本号 - */ - @Query("SELECT MAX(w.version) FROM WorkflowDefinition w WHERE w.code = :code AND w.deleted = false") - Integer findLatestVersionByCode(@Param("code") String code); - - /** - * 根据编码查询工作流定义 - * - * @param code 工作流编码 - * @return 工作流定义 - */ - WorkflowDefinition findByCodeAndDeletedFalse(String code); -} \ No newline at end of file + boolean existsByKeyAndDeletedFalse(String key); +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowInstanceRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowInstanceRepository.java deleted file mode 100644 index 459dd3f7..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowInstanceRepository.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.qqchen.deploy.backend.workflow.repository; - -import com.qqchen.deploy.backend.framework.repository.IBaseRepository; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnum; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; - -/** - * 工作流实例仓库接口 - */ -@Repository -public interface IWorkflowInstanceRepository extends IBaseRepository { - - /** - * 查询指定状态的工作流实例 - */ - @Query("SELECT i FROM WorkflowInstance i WHERE i.status IN :statuses AND i.deleted = false") - List findByStatusIn(@Param("statuses") List statuses); - - /** - * 根据工作流定义ID和状态查询工作流实例 - */ - List findByWorkflowDefinitionIdAndStatus(Long workflowDefinitionId, WorkflowInstanceStatusEnum status); - - /** - * 根据工作流定义ID和状态统计工作流实例数量 - */ - Long countByWorkflowDefinitionIdAndStatus(Long workflowDefinitionId, WorkflowInstanceStatusEnum status); - - /** - * 查询项目环境的工作流实例 - */ - List findByProjectEnvIdAndDeletedFalseOrderByCreateTimeDesc(Long projectEnvId); - - /** - * 查找超过指定时间未完成的工作流实例 - */ - @Query("SELECT wi FROM WorkflowInstance wi WHERE wi.status = :status AND wi.startTime < :beforeTime") - List findTimeoutInstances(@Param("status") WorkflowInstanceStatusEnum status, - @Param("beforeTime") LocalDateTime beforeTime); - - /** - * 查找指定工作流定义下所有未结束的实例 - */ - @Query("SELECT wi FROM WorkflowInstance wi WHERE wi.workflowDefinitionId = :definitionId AND wi.status IN :activeStatuses") - List findActiveInstancesByDefinitionId(@Param("definitionId") Long definitionId, - @Param("activeStatuses") Collection activeStatuses); - - /** - * 统计指定工作流定义下所有未结束的实例数量 - */ - @Query("SELECT COUNT(wi) FROM WorkflowInstance wi WHERE wi.workflowDefinitionId = :definitionId AND wi.status IN :activeStatuses") - Long countActiveInstancesByDefinitionId(@Param("definitionId") Long definitionId, - @Param("activeStatuses") Collection activeStatuses); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowLogRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowLogRepository.java deleted file mode 100644 index 6556658c..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowLogRepository.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.qqchen.deploy.backend.workflow.repository; - -import com.qqchen.deploy.backend.framework.repository.IBaseRepository; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowLog; -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 IWorkflowLogRepository extends IBaseRepository { - - /** - * 查询工作流实例的所有日志 - */ - @Query("SELECT l FROM WorkflowLog l WHERE l.workflowInstance.id = :instanceId AND l.deleted = false ORDER BY l.createTime") - List findByWorkflowInstanceId(@Param("instanceId") Long instanceId); - - /** - * 查询节点实例的所有日志 - */ - @Query("SELECT l FROM WorkflowLog l WHERE l.workflowInstance.id = :instanceId AND l.nodeId = :nodeId AND l.deleted = false ORDER BY l.createTime") - List findByWorkflowInstanceIdAndNodeId(@Param("instanceId") Long instanceId, @Param("nodeId") String nodeId); - - /** - * 删除工作流实例的所有日志 - */ - void deleteByWorkflowInstance(WorkflowInstance instance); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowVariableRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowVariableRepository.java deleted file mode 100644 index 0122f70c..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowVariableRepository.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.qqchen.deploy.backend.workflow.repository; - -import com.qqchen.deploy.backend.framework.repository.IBaseRepository; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowVariable; -import com.qqchen.deploy.backend.workflow.enums.VariableScopeEnum; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Optional; - -/** - * 工作流变量仓库接口 - */ -@Repository -public interface IWorkflowVariableRepository extends IBaseRepository { - - /** - * 查询工作流实例的所有变量 - */ - @Query("SELECT v FROM WorkflowVariable v WHERE v.workflowInstance = :instance AND v.deleted = false") - List findByWorkflowInstance(@Param("instance") WorkflowInstance instance); - - /** - * 查询工作流实例的指定作用域的变量 - */ - @Query("SELECT v FROM WorkflowVariable v WHERE v.workflowInstance = :instance AND v.scope = :scope AND v.deleted = false") - List findByWorkflowInstanceAndScope(@Param("instance") WorkflowInstance instance, @Param("scope") String scope); - - /** - * 查询工作流实例的指定变量 - */ - Optional findByWorkflowInstanceAndName(WorkflowInstance instance, String name); - - /** - * 删除工作流实例的所有变量 - */ - void deleteByWorkflowInstance(WorkflowInstance instance); - - /** - * 查询工作流实例的指定作用域和节点的变量 - */ - @Query("SELECT v FROM WorkflowVariable v WHERE v.workflowInstance = :instance AND v.scope = :scope AND v.nodeId = :nodeId AND v.deleted = false") - List findByWorkflowInstanceAndScopeAndNodeId( - @Param("instance") WorkflowInstance instance, - @Param("scope") String scope, - @Param("nodeId") String nodeId); - - /** - * 查询工作流实例的指定名称和作用域的变量 - */ - @Query("SELECT v FROM WorkflowVariable v WHERE v.workflowInstance = :instance AND v.name = :name AND v.scope = :scope AND v.deleted = false") - Optional findByWorkflowInstanceAndNameAndScope( - @Param("instance") WorkflowInstance instance, - @Param("name") String name, - @Param("scope") String scope); - - /** - * 根据工作流实例ID查询所有变量 - * - * @param workflowInstanceId 工作流实例ID - * @return 变量列表 - */ - @Query("SELECT v FROM WorkflowVariable v WHERE v.workflowInstance.id = :workflowInstanceId AND v.deleted = false") - List findByWorkflowInstanceId(@Param("workflowInstanceId") Long workflowInstanceId); - - /** - * 根据工作流实例ID和作用域查询变量列表 - * - * @param workflowInstanceId 工作流实例ID - * @param scope 变量作用域 - * @return 变量列表 - */ - @Query("SELECT v FROM WorkflowVariable v WHERE v.workflowInstance.id = :workflowInstanceId AND v.scope = :scope AND v.deleted = false") - List findByWorkflowInstanceIdAndScope( - @Param("workflowInstanceId") Long workflowInstanceId, - @Param("scope") VariableScopeEnum scope); - - /** - * 删除工作流实例变量 - * - * @param workflowInstanceId 工作流实例ID - */ - @Modifying - @Query("DELETE FROM WorkflowVariable v WHERE v.workflowInstance.id = :workflowInstanceId") - void deleteWorkflowInstanceVariable(@Param("workflowInstanceId") Long workflowInstanceId); - - /** - * 删除工作流实例的所有变量(逻辑删除) - */ - @Modifying - @Query("UPDATE WorkflowVariable v SET v.deleted = true, v.updateTime = CURRENT_TIMESTAMP WHERE v.workflowInstance.id = :workflowInstanceId AND v.deleted = false") - void deleteByWorkflowInstanceId(@Param("workflowInstanceId") Long workflowInstanceId); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/INodeInstanceService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/INodeInstanceService.java deleted file mode 100644 index b50109da..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/INodeInstanceService.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service; - -import com.qqchen.deploy.backend.framework.service.IBaseService; -import com.qqchen.deploy.backend.workflow.dto.NodeInstanceDTO; -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; - -import java.util.List; - -/** - * 节点实例服务接口 - */ -public interface INodeInstanceService extends IBaseService { - - /** - * 根据工作流实例ID查询节点列表 - * - * @param workflowInstanceId 工作流实例ID - * @return 节点列表 - */ - List findByWorkflowInstanceId(Long workflowInstanceId); - - /** - * 根据工作流实例ID和状态查询节点列表 - * - * @param workflowInstanceId 工作流实例ID - * @param status 状态 - * @return 节点列表 - */ - List findByWorkflowInstanceIdAndStatus(Long workflowInstanceId, NodeStatusEnum status); - - /** - * 更新节点状态 - * - * @param id 节点ID - * @param status 状态 - * @param output 输出结果 - * @param error 错误信息 - */ - void updateStatus(Long id, NodeStatusEnum status, String output, String error); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/INodeTypeService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/INodeTypeService.java deleted file mode 100644 index 91a274a5..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/INodeTypeService.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service; - -import com.qqchen.deploy.backend.framework.service.IBaseService; -import com.qqchen.deploy.backend.workflow.dto.NodeTypeDTO; -import com.qqchen.deploy.backend.workflow.entity.NodeType; - -/** - * 节点类型服务接口 - */ -public interface INodeTypeService extends IBaseService { - - /** - * 根据编码查询节点类型 - * - * @param code 节点类型编码 - * @return 节点类型 - */ - NodeTypeDTO findByCode(String code); - - - /** - * 启用节点类型 - * - * @param id 节点类型ID - */ - void enable(Long id); - - /** - * 禁用节点类型 - * - * @param id 节点类型ID - */ - void disable(Long id); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDefinitionService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDefinitionService.java index 3d134ec1..022b763c 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDefinitionService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDefinitionService.java @@ -3,93 +3,44 @@ package com.qqchen.deploy.backend.workflow.service; import com.qqchen.deploy.backend.framework.service.IBaseService; import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; +import org.flowable.engine.runtime.ProcessInstance; -import java.util.List; +import java.util.Map; /** * 工作流定义服务接口 */ public interface IWorkflowDefinitionService extends IBaseService { - + /** - * 创建工作流定义 + * 部署工作流 * * @param dto 工作流定义DTO - * @return 工作流定义 + * @return 工作流定义DTO */ - WorkflowDefinitionDTO create(WorkflowDefinitionDTO dto); - + WorkflowDefinitionDTO deployWorkflow(WorkflowDefinitionDTO dto); + /** - * 更新工作流定义 + * 启动工作流实例 * - * @param id 工作流定义ID - * @param dto 工作流定义DTO - * @return 工作流定义 + * @param processKey 流程标识 + * @param businessKey 业务标识 + * @param variables 流程变量 + * @return 流程实例 */ - WorkflowDefinitionDTO update(Long id, WorkflowDefinitionDTO dto); - + ProcessInstance startWorkflow(String processKey, String businessKey, Map variables); + /** - * 发布工作流定义 + * 挂起工作流实例 * - * @param id 工作流定义ID - * @return 工作流定义 + * @param processInstanceId 流程实例ID */ - WorkflowDefinitionDTO publish(Long id); - + void suspendWorkflow(String processInstanceId); + /** - * 禁用工作流定义 + * 恢复工作流实例 * - * @param id 工作流定义ID - * @return 工作流定义 + * @param processInstanceId 流程实例ID */ - WorkflowDefinitionDTO disable(Long id); - - /** - * 创建新版本 - * - * @param id 工作流定义ID - * @return 工作流定义 - */ - WorkflowDefinitionDTO createNewVersion(Long id); - - /** - * 根据编码查询最新版本 - * - * @param code 工作流编码 - * @return 工作流定义 - */ - WorkflowDefinitionDTO findLatestByCode(String code); - - /** - * 根据编码和版本号查询 - * - * @param code 工作流编码 - * @param version 版本号 - * @return 工作流定义 - */ - WorkflowDefinitionDTO findByCodeAndVersion(String code, Integer version); - - /** - * 查询所有版本 - * - * @param code 工作流编码 - * @return 工作流定义列表 - */ - List findAllVersions(String code); - - /** - * 验证工作流定义 - * - * @param id 工作流定义ID - * @return 验证结果 - */ - boolean validate(Long id); - - /** - * 启用工作流定义 - * - * @param id 工作流定义ID - * @return 工作流定义 - */ - WorkflowDefinitionDTO enable(Long id); -} \ No newline at end of file + void resumeWorkflow(String processInstanceId); +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDesignService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDesignService.java new file mode 100644 index 00000000..81e81760 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDesignService.java @@ -0,0 +1,17 @@ +package com.qqchen.deploy.backend.workflow.service; + +import com.qqchen.deploy.backend.framework.service.IBaseService; +import com.qqchen.deploy.backend.workflow.dto.WorkflowDesignDTO; +import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; +import com.qqchen.deploy.backend.workflow.query.WorkflowDefinitionQuery; + +/** + * 工作流设计服务接口 + */ +public interface IWorkflowDesignService extends IBaseService { + + /** + * 保存工作流设计 + */ + WorkflowDesignDTO saveWorkflowDesign(WorkflowDesignDTO dto) throws Exception; +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowEngineService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowEngineService.java deleted file mode 100644 index 37b1e553..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowEngineService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service; - -import com.qqchen.deploy.backend.workflow.dto.request.WorkflowStartRequest; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; - -/** - * 工作流执行引擎接口 - */ -public interface IWorkflowEngineService { - - /** - * 启动工作流实例 - */ - WorkflowInstance startWorkflow(WorkflowStartRequest request); - -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowInstanceService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowInstanceService.java deleted file mode 100644 index 1b4a429b..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowInstanceService.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service; - -import com.qqchen.deploy.backend.framework.service.IBaseService; -import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; - -import java.util.Map; - -/** - * 工作流实例服务接口 - */ -public interface IWorkflowInstanceService extends IBaseService { - - /** - * 创建工作流实例 - * - * @param definitionId 工作流定义ID - * @param businessKey 业务标识 - * @param variables 初始变量 - * @return 工作流实例 - */ - WorkflowInstanceDTO createInstance(Long definitionId, String businessKey, Map variables); - - /** - * 启动工作流实例 - * - * @param id 实例ID - * @return 工作流实例 - */ - WorkflowInstanceDTO startInstance(Long id); - - /** - * 暂停工作流实例 - * - * @param id 实例ID - * @return 工作流实例 - */ - WorkflowInstanceDTO pauseInstance(Long id); - - /** - * 恢复工作流实例 - * - * @param id 实例ID - * @return 工作流实例 - */ - WorkflowInstanceDTO resumeInstance(Long id); - - /** - * 终止工作流实例 - * - * @param id 实例ID - * @param reason 终止原因 - * @return 工作流实例 - */ - WorkflowInstanceDTO terminateInstance(Long id, String reason); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowLogService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowLogService.java deleted file mode 100644 index a5d903c1..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowLogService.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service; - -import com.qqchen.deploy.backend.framework.service.IBaseService; -import com.qqchen.deploy.backend.system.enums.LogLevelEnum; -import com.qqchen.deploy.backend.workflow.dto.WorkflowLogDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowLog; - -import java.util.List; - -/** - * 工作流日志服务接口 - */ -public interface IWorkflowLogService extends IBaseService { - - /** - * 记录日志 (内部使用,由工作流引擎调用) - * - * @param instance 工作流实例 - * @param nodeId 节点ID - * @param level 日志级别 - * @param message 日志内容 - * @param detail 详细信息 - * @return 工作流日志 - */ - WorkflowLog log(WorkflowInstance instance, String nodeId, LogLevelEnum level, String message, String detail); - - /** - * 记录日志 (外部接口使用) - * - * @param workflowInstanceId 工作流实例ID - * @param nodeId 节点ID - * @param message 日志内容 - * @param level 日志级别 - * @param detail 详细信息 - */ - void recordLog(Long workflowInstanceId, String nodeId, String message, LogLevelEnum level, String detail); - - /** - * 查询工作流实例的所有日志 - * - * @param workflowInstanceId 工作流实例ID - * @return 日志列表 - */ - List getLogs(Long workflowInstanceId); - - /** - * 查询节点实例的所有日志 - * - * @param workflowInstanceId 工作流实例ID - * @param nodeId 节点ID - * @return 日志列表 - */ - List getNodeLogs(Long workflowInstanceId, String nodeId); - - /** - * 删除工作流实例的所有日志 - * - * @param workflowInstance 工作流实例 - */ - void deleteLogs(WorkflowInstance workflowInstance); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowVariableService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowVariableService.java deleted file mode 100644 index adc6447e..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowVariableService.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service; - -import com.qqchen.deploy.backend.framework.service.IBaseService; -import com.qqchen.deploy.backend.workflow.dto.WorkflowVariableDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowVariable; -import com.qqchen.deploy.backend.workflow.enums.VariableScopeEnum; - -import java.util.Map; - -/** - * 工作流变量服务接口 - */ -public interface IWorkflowVariableService extends IBaseService { - - /** - * 设置变量 - * - * @param variables 变量映射 - */ - void setVariables(Long workflowInstanceId, Map variables); - - /** - * 获取所有变量 - * - * @return 变量映射 - */ - Map getVariables(Long workflowInstanceId); - - /** - * 获取指定作用域的变量 - * - * @param scope 变量作用域 - * @return 变量映射 - */ - Map getVariablesByScope(Long workflowInstanceId, VariableScopeEnum scope); - - /** - * 清除实例的所有变量 - * - */ - void clearVariables(Long workflowInstanceId); -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/NodeInstanceServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/NodeInstanceServiceImpl.java deleted file mode 100644 index 32686c0f..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/NodeInstanceServiceImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service.impl; - -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.framework.exception.BusinessException; -import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; -import com.qqchen.deploy.backend.workflow.converter.NodeInstanceConverter; -import com.qqchen.deploy.backend.workflow.dto.NodeInstanceDTO; -import com.qqchen.deploy.backend.workflow.entity.NodeInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; -import com.qqchen.deploy.backend.workflow.repository.INodeInstanceRepository; -import com.qqchen.deploy.backend.workflow.service.INodeInstanceService; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 节点实例服务实现类 - */ -@Service -public class NodeInstanceServiceImpl extends BaseServiceImpl implements INodeInstanceService { - - @Resource - private INodeInstanceRepository nodeInstanceRepository; - - @Resource - private NodeInstanceConverter nodeInstanceConverter; - - @Override - public List findByWorkflowInstanceId(Long workflowInstanceId) { - return nodeInstanceRepository.findByWorkflowInstanceId(workflowInstanceId) - .stream() - .map(nodeInstanceConverter::toDto) - .collect(Collectors.toList()); - } - - @Override - public List findByWorkflowInstanceIdAndStatus(Long workflowInstanceId, NodeStatusEnum status) { - return nodeInstanceRepository.findByWorkflowInstanceIdAndStatus(workflowInstanceId, status) - .stream() - .map(nodeInstanceConverter::toDto) - .collect(Collectors.toList()); - } - - @Override - @Transactional - public void updateStatus(Long id, NodeStatusEnum status, String output, String error) { - NodeInstance node = nodeInstanceRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NODE_NOT_FOUND)); - node.setStatus(status); - node.setOutput(output); - node.setError(error); - - if (NodeStatusEnum.RUNNING.equals(status)) { - node.setStartTime(LocalDateTime.now()); - } else if (NodeStatusEnum.COMPLETED.equals(status) || - NodeStatusEnum.FAILED.equals(status) || - NodeStatusEnum.CANCELLED.equals(status) || - NodeStatusEnum.SKIPPED.equals(status)) { - node.setEndTime(LocalDateTime.now()); - } - - nodeInstanceRepository.save(node); - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/NodeTypeServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/NodeTypeServiceImpl.java deleted file mode 100644 index cb46209f..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/NodeTypeServiceImpl.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service.impl; - -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.framework.exception.BusinessException; -import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; -import com.qqchen.deploy.backend.workflow.converter.JsonConverter; -import com.qqchen.deploy.backend.workflow.converter.NodeTypeConverter; -import com.qqchen.deploy.backend.workflow.dto.NodeTypeDTO; -import com.qqchen.deploy.backend.workflow.entity.NodeType; -import com.qqchen.deploy.backend.workflow.repository.INodeTypeRepository; -import com.qqchen.deploy.backend.workflow.service.INodeTypeService; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * 节点类型服务实现类 - */ -@Service -public class NodeTypeServiceImpl extends BaseServiceImpl implements INodeTypeService { - - @Resource - private INodeTypeRepository nodeTypeRepository; - - @Resource - private NodeTypeConverter nodeTypeConverter; - - @Resource - private JsonConverter jsonConverter; - - @Override - public NodeTypeDTO findByCode(String code) { - return nodeTypeRepository.findByCodeAndDeletedFalse(code) - .map(nodeTypeConverter::toDto) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NODE_TYPE_NOT_FOUND)); - } - - @Override - @Transactional - public void enable(Long id) { - NodeType nodeType = nodeTypeRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NODE_TYPE_NOT_FOUND)); - nodeType.setEnabled(true); - nodeTypeRepository.save(nodeType); - } - - @Override - @Transactional - public void disable(Long id) { - NodeType nodeType = nodeTypeRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NODE_TYPE_NOT_FOUND)); - nodeType.setEnabled(false); - nodeTypeRepository.save(nodeType); - } -} \ 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 ef342bfb..fb7ceb44 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 @@ -1,22 +1,19 @@ package com.qqchen.deploy.backend.workflow.service.impl; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; -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.IWorkflowDefinitionRepository; import com.qqchen.deploy.backend.workflow.service.IWorkflowDefinitionService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.RepositoryService; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.repository.Deployment; +import org.flowable.engine.runtime.ProcessInstance; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; +import java.util.Map; /** * 工作流定义服务实现 @@ -27,203 +24,67 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl new BusinessException(ResponseCode.WORKFLOW_NOT_FOUND)); - - // 只有草稿状态可以修改 - if (current.getStatus() != WorkflowDefinitionStatusEnum.DRAFT) { - throw new BusinessException(ResponseCode.WORKFLOW_NOT_DRAFT); + @Transactional(rollbackFor = Exception.class) + public ProcessInstance startWorkflow(String processKey, String businessKey, Map variables) { + try { + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey( + processKey, + businessKey, + variables + ); + log.info("Started workflow instance: {}", processInstance.getId()); + return processInstance; + } catch (Exception e) { + log.error("Failed to start workflow: {}", processKey, e); + throw new RuntimeException("Failed to start workflow", e); } - - // 检查编码是否已存在(排除自身) - if (!Objects.equals(current.getCode(), dto.getCode()) && - workflowDefinitionRepository.existsByCodeAndDeletedFalse(dto.getCode())) { - throw new BusinessException(ResponseCode.WORKFLOW_CODE_EXISTS); - } - - // 更新基本信息 - current.setName(dto.getName()); - current.setDescription(dto.getDescription()); - current.setNodeConfig(dto.getNodeConfig()); - current.setTransitionConfig(dto.getTransitionConfig()); - current.setFormDefinition(dto.getFormDefinition()); - current.setGraphDefinition(dto.getGraphDefinition()); - - // 保存更新 - current = workflowDefinitionRepository.save(current); - - return workflowDefinitionConverter.toDto(current); } @Override - @Transactional - public WorkflowDefinitionDTO publish(Long id) { - // 获取当前工作流定义 - WorkflowDefinition current = workflowDefinitionRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NOT_FOUND)); - - // 验证当前状态 - if (current.getStatus() != WorkflowDefinitionStatusEnum.DRAFT) { - throw new BusinessException(ResponseCode.WORKFLOW_NOT_DRAFT); + public void suspendWorkflow(String processInstanceId) { + try { + runtimeService.suspendProcessInstanceById(processInstanceId); + log.info("Suspended workflow instance: {}", processInstanceId); + } catch (Exception e) { + log.error("Failed to suspend workflow instance: {}", processInstanceId, e); + throw new RuntimeException("Failed to suspend workflow instance", e); } - - // 验证工作流定义 - if (!validate(id)) { - throw new BusinessException(ResponseCode.WORKFLOW_CONFIG_INVALID); - } - - // 更新状态 - current.setStatus(WorkflowDefinitionStatusEnum.PUBLISHED); - current = workflowDefinitionRepository.save(current); - - return workflowDefinitionConverter.toDto(current); } @Override - @Transactional - public WorkflowDefinitionDTO disable(Long id) { - // 获取当前工作流定义 - WorkflowDefinition current = workflowDefinitionRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NOT_FOUND)); - - // 验证当前状态 - if (current.getStatus() != WorkflowDefinitionStatusEnum.PUBLISHED) { - throw new BusinessException(ResponseCode.WORKFLOW_NOT_PUBLISHED); + public void resumeWorkflow(String processInstanceId) { + try { + runtimeService.activateProcessInstanceById(processInstanceId); + log.info("Resumed workflow instance: {}", processInstanceId); + } catch (Exception e) { + log.error("Failed to resume workflow instance: {}", processInstanceId, e); + throw new RuntimeException("Failed to resume workflow instance", e); } - - // 更新状态 - current.setStatus(WorkflowDefinitionStatusEnum.DISABLED); - current = workflowDefinitionRepository.save(current); - - return workflowDefinitionConverter.toDto(current); } - - @Override - @Transactional - public WorkflowDefinitionDTO enable(Long id) { - // 获取当前工作流定义 - WorkflowDefinition current = workflowDefinitionRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NOT_FOUND)); - - // 验证当前状态 - if (current.getStatus() != WorkflowDefinitionStatusEnum.DISABLED) { - throw new BusinessException(ResponseCode.WORKFLOW_NOT_DISABLED); - } - - // 更新状态 - current.setStatus(WorkflowDefinitionStatusEnum.PUBLISHED); - current = workflowDefinitionRepository.save(current); - - return workflowDefinitionConverter.toDto(current); - } - - @Override - public WorkflowDefinitionDTO findLatestByCode(String code) { - return workflowDefinitionRepository.findLatestByCode(code) - .map(workflowDefinitionConverter::toDto) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NOT_FOUND)); - } - - @Override - public List findAllVersions(String code) { - return workflowDefinitionRepository.findAllVersionsByCode(code) - .stream() - .map(workflowDefinitionConverter::toDto) - .collect(Collectors.toList()); - } - - @Override - public boolean validate(Long id) { - WorkflowDefinition definition = workflowDefinitionRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NOT_FOUND)); - - // 1. 验证节点配置的完整性 - if (definition.getNodeConfig() == null || definition.getNodeConfig().isEmpty()) { - throw new BusinessException(ResponseCode.WORKFLOW_NODE_CONFIG_EMPTY); - } - - // 2. 验证流转配置的完整性 - if (definition.getTransitionConfig() == null || definition.getTransitionConfig().isEmpty()) { - throw new BusinessException(ResponseCode.WORKFLOW_TRANSITION_CONFIG_EMPTY); - } - - // 3. 验证表单定义的完整性 - if (definition.getFormDefinition() == null || definition.getFormDefinition().isEmpty()) { - throw new BusinessException(ResponseCode.WORKFLOW_FORM_CONFIG_EMPTY); - } - - // 4. 验证图形信息的完整性 - if (definition.getGraphDefinition() == null || definition.getGraphDefinition().isEmpty()) { - throw new BusinessException(ResponseCode.WORKFLOW_GRAPH_CONFIG_EMPTY); - } - - // TODO: 实现更详细的验证逻辑 - // 1. 验证节点之间的连接关系 - // 2. 验证表单字段的合法性 - // 3. 验证图形布局的合理性 - return true; - } - - @Override - @Transactional(readOnly = true) - public WorkflowDefinitionDTO findByCodeAndVersion(String code, Integer version) { - return workflowDefinitionConverter.toDto(workflowDefinitionRepository.findByCodeAndVersionAndDeletedFalse(code, version) - .orElse(null)); - } - - @Override - @Transactional - public WorkflowDefinitionDTO createNewVersion(Long id) { - // 获取原工作流定义 - WorkflowDefinition oldDefinition = workflowDefinitionRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NOT_FOUND)); - - // 获取最新版本号 - Integer latestVersion = workflowDefinitionRepository.findLatestVersionByCode(oldDefinition.getCode()); - Integer newVersion = latestVersion != null ? latestVersion + 1 : 1; - - // 创建新版本 - WorkflowDefinition newDefinition = new WorkflowDefinition(); - newDefinition.setCode(oldDefinition.getCode()); - newDefinition.setName(oldDefinition.getName()); - newDefinition.setDescription(oldDefinition.getDescription()); - newDefinition.setStatus(WorkflowDefinitionStatusEnum.DRAFT); - newDefinition.setEnabled(true); - newDefinition.setNodeConfig(oldDefinition.getNodeConfig()); - newDefinition.setTransitionConfig(oldDefinition.getTransitionConfig()); - newDefinition.setFormDefinition(oldDefinition.getFormDefinition()); - newDefinition.setGraphDefinition(oldDefinition.getGraphDefinition()); - - // 保存新版本 - return workflowDefinitionConverter.toDto(workflowDefinitionRepository.save(newDefinition)); - } -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDesignServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDesignServiceImpl.java new file mode 100644 index 00000000..0e3b1a05 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDesignServiceImpl.java @@ -0,0 +1,47 @@ +package com.qqchen.deploy.backend.workflow.service.impl; + +import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; +import com.qqchen.deploy.backend.workflow.dto.WorkflowDesignDTO; +import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; +import com.qqchen.deploy.backend.workflow.query.WorkflowDefinitionQuery; +import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository; +import com.qqchen.deploy.backend.workflow.service.IWorkflowDefinitionService; +import com.qqchen.deploy.backend.workflow.service.IWorkflowDesignService; +import com.qqchen.deploy.backend.workflow.util.BpmnConverter; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 工作流设计服务实现 + */ +@Service +public class WorkflowDesignServiceImpl extends BaseServiceImpl implements IWorkflowDesignService { + + @Resource + private IWorkflowDefinitionService workflowDefinitionService; + + @Resource + private IWorkflowDefinitionRepository workflowDefinitionRepository; + + @Resource + private BpmnConverter bpmnConverter; + + @Override + @Transactional(rollbackFor = Exception.class) + public WorkflowDesignDTO saveWorkflowDesign(WorkflowDesignDTO dto) throws Exception { + // 转换图形JSON为BPMN XML + String bpmnXml = bpmnConverter.convertToBpmnXml(dto.getGraphJson(), dto.getKey()); + + // 创建工作流定义 + WorkflowDefinition definition = new WorkflowDefinition(); + definition.setName(dto.getName()); + definition.setKey(dto.getKey()); + definition.setDescription(dto.getDescription()); + definition.setGraphJson(dto.getGraphJson()); + definition.setBpmnXml(bpmnXml); + + // 保存工作流定义 + return super.converter.toDto(workflowDefinitionRepository.save(definition)); + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowEngineServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowEngineServiceImpl.java deleted file mode 100644 index 5f03bbff..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowEngineServiceImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service.impl; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.workflow.dto.request.WorkflowStartRequest; -import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.executor.INodeExecutor; -import com.qqchen.deploy.backend.workflow.engine.model.NodeConfig; -import com.qqchen.deploy.backend.workflow.engine.model.WorkflowGraph; -import com.qqchen.deploy.backend.workflow.engine.parser.WorkflowDefinitionParser; -import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum; -import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnum; -import com.qqchen.deploy.backend.workflow.repository.INodeInstanceRepository; -import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository; -import com.qqchen.deploy.backend.workflow.repository.IWorkflowInstanceRepository; -import com.qqchen.deploy.backend.workflow.service.IWorkflowEngineService; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.Map; - -@Slf4j -@Component -public class WorkflowEngineServiceImpl implements IWorkflowEngineService { - - @Resource - private IWorkflowDefinitionRepository workflowDefinitionRepository; - - @Resource - private IWorkflowInstanceRepository workflowInstanceRepository; - - @Resource - private INodeInstanceRepository nodeInstanceRepository; - - @Resource - @Lazy - private Map nodeExecutors; - - @Resource - private ObjectMapper objectMapper; - - @Resource - private WorkflowDefinitionParser workflowDefinitionParser; - - @Override - @Transactional - public WorkflowInstance startWorkflow(WorkflowStartRequest request) { - // 1. 获取工作流定义 - WorkflowDefinition definition = workflowDefinitionRepository.findByCodeAndDeletedFalse(request.getWorkflowCode()); - if (definition == null) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NOT_FOUND); - } - - // 2. 检查工作流定义状态 - if (definition.getStatus() != WorkflowDefinitionStatusEnum.PUBLISHED) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NOT_PUBLISHED); - } - - // 3. 创建工作流实例 - WorkflowInstance workflowInstance = new WorkflowInstance(); - workflowInstance.setWorkflowDefinition(definition); - workflowInstance.setBusinessKey(request.getBusinessKey()); - workflowInstance.setStatus(WorkflowInstanceStatusEnum.RUNNING); - workflowInstance.setCreateTime(LocalDateTime.now()); - workflowInstanceRepository.save(workflowInstance); - - // 5. 解析工作流配置 - WorkflowGraph graph = workflowDefinitionParser.parse(definition); - - // 6. 获取并执行开始节点 - NodeConfig startNode = graph.getStartNode(); - INodeExecutor executor = nodeExecutors.get(startNode.getType()); - executor.execute(workflowInstance, graph, startNode); - return workflowInstance; - } - -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowInstanceServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowInstanceServiceImpl.java deleted file mode 100644 index fb5f9792..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowInstanceServiceImpl.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service.impl; - -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.framework.exception.BusinessException; -import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; -import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnum; -import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum; -import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository; -import com.qqchen.deploy.backend.workflow.repository.IWorkflowInstanceRepository; -import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.Map; - -/** - * 工作流实例服务实现类 - */ -@Slf4j -@Service -public class WorkflowInstanceServiceImpl extends BaseServiceImpl implements IWorkflowInstanceService { - - @Resource - private IWorkflowDefinitionRepository workflowDefinitionRepository; - - @Resource - private IWorkflowInstanceRepository workflowInstanceRepository; - - - @Override - @Transactional - public WorkflowInstanceDTO createInstance(Long definitionId, String businessKey, Map variables) { - // 1. 查询工作流定义 - WorkflowDefinition definition = workflowDefinitionRepository.findById(definitionId) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NOT_FOUND)); - - // 2. 检查工作流定义状态 - if (definition.getStatus() != WorkflowDefinitionStatusEnum.PUBLISHED) { - throw new BusinessException(ResponseCode.WORKFLOW_NOT_PUBLISHED); - } - if (!definition.getEnabled()) { - throw new BusinessException(ResponseCode.WORKFLOW_DISABLED); - } - - // 3. 创建工作流实例 - WorkflowInstance instance = new WorkflowInstance(); - instance.setDefinition(definition); - instance.setBusinessKey(businessKey); - instance.setStatus(WorkflowInstanceStatusEnum.CREATED); - final WorkflowInstance savedInstance = workflowInstanceRepository.save(instance); - - return converter.toDto(savedInstance); - } - - @Override - @Transactional - public WorkflowInstanceDTO startInstance(Long id) { - // 1. 查询工作流实例 - WorkflowInstance instance = workflowInstanceRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_INSTANCE_NOT_FOUND)); - - // 2. 检查状态 - if (instance.getStatus() != WorkflowInstanceStatusEnum.CREATED) { - throw new BusinessException(ResponseCode.WORKFLOW_INSTANCE_NOT_RUNNING); - } - - // 3. 更新状态 - instance.setStatus(WorkflowInstanceStatusEnum.RUNNING); - instance.setStartTime(LocalDateTime.now()); - instance = workflowInstanceRepository.save(instance); - - return converter.toDto(instance); - } - - @Override - @Transactional - public WorkflowInstanceDTO pauseInstance(Long id) { - // 1. 查询工作流实例 - WorkflowInstance instance = workflowInstanceRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_INSTANCE_NOT_FOUND)); - - // 2. 检查状态 - if (!instance.getStatus().canPause()) { - throw new BusinessException(ResponseCode.WORKFLOW_INSTANCE_NOT_RUNNING); - } - - // 3. 更新状态 - instance.setStatus(WorkflowInstanceStatusEnum.PAUSED); - instance = workflowInstanceRepository.save(instance); - - return converter.toDto(instance); - } - - @Override - @Transactional - public WorkflowInstanceDTO resumeInstance(Long id) { - // 1. 查询工作流实例 - WorkflowInstance instance = workflowInstanceRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_INSTANCE_NOT_FOUND)); - - // 2. 检查状态 - if (!instance.getStatus().canResume()) { - throw new BusinessException(ResponseCode.WORKFLOW_INSTANCE_NOT_RUNNING); - } - - // 3. 更新状态 - instance.setStatus(WorkflowInstanceStatusEnum.RUNNING); - instance = workflowInstanceRepository.save(instance); - - return converter.toDto(instance); - } - - @Override - @Transactional - public WorkflowInstanceDTO terminateInstance(Long id, String reason) { - // 1. 查询工作流实例 - WorkflowInstance instance = workflowInstanceRepository.findById(id) - .orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_INSTANCE_NOT_FOUND)); - - // 2. 检查状态 - if (instance.getStatus().isFinalStatus()) { - throw new BusinessException(ResponseCode.WORKFLOW_INSTANCE_NOT_RUNNING); - } - - // 3. 更新状态 - instance.setStatus(WorkflowInstanceStatusEnum.TERMINATED); - instance.setEndTime(LocalDateTime.now()); - instance.setError(reason); - instance = workflowInstanceRepository.save(instance); - - return converter.toDto(instance); - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowLogServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowLogServiceImpl.java deleted file mode 100644 index 5896ed21..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowLogServiceImpl.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service.impl; - -import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; -import com.qqchen.deploy.backend.system.enums.LogLevelEnum; -import com.qqchen.deploy.backend.workflow.dto.WorkflowLogDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowLog; -import com.qqchen.deploy.backend.workflow.repository.IWorkflowLogRepository; -import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService; -import com.qqchen.deploy.backend.workflow.service.IWorkflowLogService; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 工作流日志服务实现类 - */ -@Slf4j -@Service -public class WorkflowLogServiceImpl extends BaseServiceImpl implements IWorkflowLogService { - - @Resource - private IWorkflowLogRepository logRepository; - - @Resource - private IWorkflowInstanceService workflowInstanceService; - - @Override - @Transactional - public WorkflowLog log(WorkflowInstance instance, String nodeId, LogLevelEnum level, String message, String detail) { - WorkflowLog workflowLog = new WorkflowLog(); - workflowLog.setWorkflowInstance(instance); - workflowLog.setNodeId(nodeId); - workflowLog.setLevel(level); - workflowLog.setMessage(message); - workflowLog.setDetail(detail); - return logRepository.save(workflowLog); - } - - @Override - @Transactional - public void recordLog(Long workflowInstanceId, String nodeId, String message, LogLevelEnum level, String detail) { - // 先获取工作流实例 - WorkflowInstance instance = workflowInstanceService.findEntityById(workflowInstanceId); - if (instance == null) { - throw new IllegalArgumentException("工作流实例不存在: " + workflowInstanceId); - } - - // 记录日志 - log(instance, nodeId, level, message, detail); - } - - @Override - @Transactional(readOnly = true) - public List getLogs(Long workflowInstanceId) { - List logs = logRepository.findByWorkflowInstanceId(workflowInstanceId); - return logs.stream().map(converter::toDto).collect(Collectors.toList()); - } - - @Override - @Transactional(readOnly = true) - public List getNodeLogs(Long workflowInstanceId, String nodeId) { - List logs = logRepository.findByWorkflowInstanceIdAndNodeId(workflowInstanceId, nodeId); - return logs.stream().map(converter::toDto).collect(Collectors.toList()); - } - - @Override - @Transactional - public void deleteLogs(WorkflowInstance workflowInstance) { - logRepository.deleteByWorkflowInstance(workflowInstance); - log.debug("删除工作流日志成功: instanceId={}", workflowInstance.getId()); - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowVariableServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowVariableServiceImpl.java deleted file mode 100644 index 0c5b9098..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowVariableServiceImpl.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.qqchen.deploy.backend.workflow.service.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.qqchen.deploy.backend.framework.enums.ResponseCode; -import com.qqchen.deploy.backend.framework.exception.BusinessException; -import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; -import com.qqchen.deploy.backend.workflow.dto.WorkflowVariableDTO; -import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; -import com.qqchen.deploy.backend.workflow.entity.WorkflowVariable; -import com.qqchen.deploy.backend.workflow.enums.VariableScopeEnum; -import com.qqchen.deploy.backend.workflow.enums.VariableTypeEnum; -import com.qqchen.deploy.backend.workflow.repository.IWorkflowVariableRepository; -import com.qqchen.deploy.backend.workflow.service.IWorkflowVariableService; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Service -public class WorkflowVariableServiceImpl extends BaseServiceImpl implements IWorkflowVariableService { - - @Resource - private IWorkflowVariableRepository variableRepository; - - @Resource - private ObjectMapper objectMapper; - - @Override - @Transactional - public void setVariables(Long workflowInstanceId, Map variables) { - if (variables == null || variables.isEmpty()) { - return; - } - - // 先删除已有的变量 - clearVariables(workflowInstanceId); - - // 批量保存新变量 - variables.forEach((key, value) -> { - try { - WorkflowVariable variable = new WorkflowVariable(); - WorkflowInstance instance = new WorkflowInstance(); - instance.setId(workflowInstanceId); - variable.setWorkflowInstance(instance); - variable.setName(key); - variable.setValue(objectMapper.writeValueAsString(value)); - - // 推断变量类型 - if (value == null) { - variable.setType(VariableTypeEnum.STRING); // 默认为字符串类型 - } else if (value instanceof String) { - variable.setType(VariableTypeEnum.STRING); - } else if (value instanceof Number) { - variable.setType(VariableTypeEnum.NUMBER); - } else if (value instanceof Boolean) { - variable.setType(VariableTypeEnum.BOOLEAN); - } else if (value instanceof Map || value.getClass().isRecord()) { - variable.setType(VariableTypeEnum.OBJECT); - } else if (value instanceof Iterable || value.getClass().isArray()) { - variable.setType(VariableTypeEnum.ARRAY); - } else { - variable.setType(VariableTypeEnum.OBJECT); - } - - variableRepository.save(variable); - } catch (JsonProcessingException e) { - throw new BusinessException(ResponseCode.WORKFLOW_VARIABLE_SERIALIZE_ERROR); - } - }); - } - - @Override - public Map getVariables(Long workflowInstanceId) { - List variables = variableRepository.findByWorkflowInstanceId(workflowInstanceId); - return deserializeVariables(variables); - } - - @Override - public Map getVariablesByScope(Long workflowInstanceId, VariableScopeEnum scope) { - List variables = variableRepository.findByWorkflowInstanceIdAndScope(workflowInstanceId, scope); - return deserializeVariables(variables); - } - - @Override - @Transactional - public void clearVariables(Long workflowInstanceId) { - variableRepository.deleteByWorkflowInstanceId(workflowInstanceId); - } - - private Map deserializeVariables(List variables) { - Map result = new HashMap<>(); - variables.forEach(variable -> { - try { - Object value = objectMapper.readValue(variable.getValue(), Object.class); - result.put(variable.getName(), value); - } catch (JsonProcessingException e) { - throw new BusinessException(ResponseCode.WORKFLOW_VARIABLE_DESERIALIZE_ERROR); - } - }); - return result; - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/util/BpmnConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/util/BpmnConverter.java new file mode 100644 index 00000000..91e9ff28 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/util/BpmnConverter.java @@ -0,0 +1,112 @@ +package com.qqchen.deploy.backend.workflow.util; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.flowable.bpmn.BpmnAutoLayout; +import org.flowable.bpmn.model.*; +import org.flowable.bpmn.model.Process; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * BPMN转换工具类 + */ +@Component +public class BpmnConverter { + + private final ObjectMapper objectMapper; + + public BpmnConverter(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + /** + * 将X6 JSON转换为BPMN XML + */ + public String convertToBpmnXml(String x6Json, String processId) throws Exception { + JsonNode jsonNode = objectMapper.readTree(x6Json); + + // 创建BPMN模型 + BpmnModel bpmnModel = new BpmnModel(); + Process process = new Process(); + bpmnModel.addProcess(process); + + process.setId(processId); + process.setName(processId); + + // 解析节点 + Map elementMap = new HashMap<>(); + JsonNode cells = jsonNode.get("cells"); + if (cells != null) { + for (JsonNode cell : cells) { + String shape = cell.get("shape").asText(); + String id = cell.get("id").asText(); + String label = cell.path("data").path("label").asText(id); + + FlowElement element = null; + switch (shape) { + case "start": + StartEvent startEvent = new StartEvent(); + startEvent.setId(id); + startEvent.setName(label); + element = startEvent; + break; + case "end": + EndEvent endEvent = new EndEvent(); + endEvent.setId(id); + endEvent.setName(label); + element = endEvent; + break; + case "userTask": + UserTask userTask = new UserTask(); + userTask.setId(id); + userTask.setName(label); + element = userTask; + break; + case "serviceTask": + ServiceTask serviceTask = new ServiceTask(); + serviceTask.setId(id); + serviceTask.setName(label); + element = serviceTask; + break; + } + + if (element != null) { + process.addFlowElement(element); + elementMap.put(id, element); + } + } + + // 解析连线 + for (JsonNode cell : cells) { + if (cell.has("source") && cell.has("target")) { + String sourceId = cell.get("source").get("cell").asText(); + String targetId = cell.get("target").get("cell").asText(); + String id = cell.get("id").asText(); + + FlowElement sourceElement = elementMap.get(sourceId); + FlowElement targetElement = elementMap.get(targetId); + + if (sourceElement != null && targetElement != null) { + SequenceFlow sequenceFlow = new SequenceFlow(); + sequenceFlow.setId(id); + sequenceFlow.setSourceRef(sourceId); + sequenceFlow.setTargetRef(targetId); + process.addFlowElement(sequenceFlow); + } + } + } + } + + // 自动布局 + new BpmnAutoLayout(bpmnModel).execute(); + + // 转换为XML + org.flowable.bpmn.converter.BpmnXMLConverter converter = + new org.flowable.bpmn.converter.BpmnXMLConverter(); + byte[] xmlBytes = converter.convertToXML(bpmnModel); + return new String(xmlBytes); + } +} diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 4ac9e7a6..78f7b1ff 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -12,7 +12,7 @@ spring: show-sql: true properties: hibernate: - format_sql: true + format_sql: false use_sql_comments: true dialect: org.hibernate.dialect.MySQL8Dialect jdbc: @@ -35,10 +35,10 @@ logging: org.springframework.web: DEBUG org.springframework.context.i18n: DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping: TRACE - org.hibernate.SQL: DEBUG + org.hibernate.SQL: INFO org.hibernate.type.descriptor.sql: TRACE - org.hibernate.type.descriptor.sql.BasicBinder: TRACE - org.hibernate.orm.jdbc.bind: TRACE + org.hibernate.type.descriptor.sql.BasicBinder: INFO + org.hibernate.orm.jdbc.bind: INFO com.qqchen.deploy.backend.framework.utils.EntityPathResolver: DEBUG com.qqchen.deploy.backend: DEBUG jwt: diff --git a/backend/src/main/resources/dashboards/workflow-context-monitor.json b/backend/src/main/resources/dashboards/workflow-context-monitor.json deleted file mode 100644 index 8b81c811..00000000 --- a/backend/src/main/resources/dashboards/workflow-context-monitor.json +++ /dev/null @@ -1,202 +0,0 @@ -{ - "annotations": { - "list": [] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": null, - "links": [], - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "Prometheus", - "fieldConfig": { - "defaults": {}, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 - }, - "hiddenSeries": false, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(workflow_variable_operations_total{type=\"set\"}[5m])", - "legendFormat": "Set Operations", - "refId": "A" - }, - { - "expr": "rate(workflow_variable_operations_total{type=\"get\"}[5m])", - "legendFormat": "Get Operations", - "refId": "B" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Variable Operations Rate", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ops", - "label": "Operations/sec", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "Prometheus", - "fieldConfig": { - "defaults": {}, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 0 - }, - "hiddenSeries": false, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "alertThreshold": true - }, - "percentage": false, - "pluginVersion": "7.5.5", - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "histogram_quantile(0.95, rate(workflow_variable_operation_duration_seconds_bucket[5m]))", - "legendFormat": "95th percentile", - "refId": "A" - }, - { - "expr": "histogram_quantile(0.50, rate(workflow_variable_operation_duration_seconds_bucket[5m]))", - "legendFormat": "Median", - "refId": "B" - } - ], - "thresholds": [], - "timeRegions": [], - "title": "Operation Duration", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "s", - "label": "Duration", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ], - "yaxis": { - "align": false - } - } - ], - "refresh": "5s", - "schemaVersion": 27, - "style": "dark", - "tags": ["workflow", "variables"], - "templating": { - "list": [] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Workflow Context Monitor", - "uid": "workflow-context", - "version": 1 -} diff --git a/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql b/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql index e8486979..39784581 100644 --- a/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql +++ b/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql @@ -263,6 +263,7 @@ CREATE TABLE sys_external_system ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外部系统表'; -- 代码仓库组表 + CREATE TABLE deploy_repo_group ( -- 基础字段 id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', @@ -382,158 +383,85 @@ CREATE TABLE deploy_repo_branch ( -- -------------------------------------------------------------------------------------- -- 工作流定义表 -CREATE TABLE wf_workflow_definition ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', - create_by VARCHAR(255) NULL COMMENT '创建人', - create_time DATETIME(6) NULL COMMENT '创建时间', - deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', - update_by VARCHAR(255) NULL COMMENT '更新人', - update_time DATETIME(6) NULL COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', +CREATE TABLE workflow_definition ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - code VARCHAR(100) NOT NULL COMMENT '工作流编码', - name VARCHAR(100) NOT NULL COMMENT '工作流名称', - description VARCHAR(255) NULL COMMENT '工作流描述', - status TINYINT NOT NULL COMMENT '工作流状态(0:草稿,1:已发布,2:已禁用)', - version_no INT NOT NULL DEFAULT 1 COMMENT '版本号', - node_config TEXT NULL COMMENT '节点配置(JSON)', - transition_config TEXT NULL COMMENT '流转配置(JSON)', - form_definition TEXT NULL COMMENT '表单定义(JSON)', - graph_definition TEXT NULL COMMENT '图形信息(JSON)', - enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用', + name VARCHAR(100) NOT NULL COMMENT '流程名称', + `key` VARCHAR(50) NOT NULL COMMENT '流程标识', + flow_version INT NOT NULL COMMENT '流程版本', + bpmn_xml TEXT NOT NULL COMMENT 'BPMN XML内容', + graph_json TEXT COMMENT 'x6 JSON内容', + description VARCHAR(255) NULL COMMENT '流程描述', - CONSTRAINT UK_workflow_definition_code_version UNIQUE (code, version_no) + CONSTRAINT UK_workflow_definition_key_version UNIQUE (`key`, flow_version) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流定义表'; - -- 工作流实例表 -CREATE TABLE wf_workflow_instance ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', - create_by VARCHAR(255) NULL COMMENT '创建人', - create_time DATETIME(6) NULL COMMENT '创建时间', - deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', - update_by VARCHAR(255) NULL COMMENT '更新人', - update_time DATETIME(6) NULL COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', +CREATE TABLE workflow_instance ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - workflow_definition_id BIGINT NOT NULL COMMENT '工作流定义ID', - business_key VARCHAR(100) NOT NULL COMMENT '业务标识', - status TINYINT NOT NULL COMMENT '状态(0:已创建,1:等待执行,2:执行中,3:已完成,4:执行失败,5:已取消,6:已暂停,7:已终止)', - start_time DATETIME(6) NULL COMMENT '开始时间', - end_time DATETIME(6) NULL COMMENT '结束时间', - error TEXT NULL COMMENT '错误信息', + process_instance_id VARCHAR(64) NOT NULL COMMENT '流程实例ID', + process_definition_id BIGINT NOT NULL COMMENT '流程定义ID', + business_key VARCHAR(64) NULL COMMENT '业务标识', + status VARCHAR(32) NOT NULL COMMENT '实例状态', + variables TEXT NULL COMMENT '流程变量(JSON)', + start_time DATETIME(6) NOT NULL COMMENT '开始时间', + end_time DATETIME(6) NULL COMMENT '结束时间', - CONSTRAINT FK_workflow_instance_definition FOREIGN KEY (workflow_definition_id) REFERENCES wf_workflow_definition (id) + CONSTRAINT FK_workflow_instance_definition FOREIGN KEY (process_definition_id) REFERENCES workflow_definition(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流实例表'; --- 节点实例表 -CREATE TABLE wf_node_instance ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', - create_by VARCHAR(255) NULL COMMENT '创建人', - create_time DATETIME(6) NULL COMMENT '创建时间', - deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', - update_by VARCHAR(255) NULL COMMENT '更新人', - update_time DATETIME(6) NULL COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', +-- 工作流节点实例表 +CREATE TABLE workflow_node_instance ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', workflow_instance_id BIGINT NOT NULL COMMENT '工作流实例ID', - node_id VARCHAR(100) NOT NULL COMMENT '节点ID', - node_type TINYINT NOT NULL COMMENT '节点类型(0:开始节点,1:结束节点,2:任务节点,3:网关节点,4:子流程节点,5:Shell脚本节点,6:审批节点,7:Jenkins任务节点,8:Git操作节点)', - name VARCHAR(100) NOT NULL COMMENT '节点名称', - status TINYINT NOT NULL COMMENT '状态(0:已创建,1:等待执行,2:执行中,3:已完成,4:执行失败,5:已取消,6:已暂停,7:已终止)', - start_time DATETIME(6) NULL COMMENT '开始时间', - end_time DATETIME(6) NULL COMMENT '结束时间', - config TEXT NULL COMMENT '节点配置(JSON)', - description TEXT NULL COMMENT '节点描述', - input TEXT NULL COMMENT '输入参数(JSON)', - output TEXT NULL COMMENT '输出结果(JSON)', - error TEXT NULL COMMENT '错误信息', - pre_node_id VARCHAR(100) NULL COMMENT '前置节点ID', + node_id VARCHAR(64) NOT NULL COMMENT '节点ID', + node_name VARCHAR(100) NOT NULL COMMENT '节点名称', + node_type VARCHAR(32) NOT NULL COMMENT '节点类型', + status VARCHAR(32) NOT NULL COMMENT '节点状态', + start_time DATETIME(6) NOT NULL COMMENT '开始时间', + end_time DATETIME(6) NULL COMMENT '结束时间', + variables TEXT NULL COMMENT '节点变量(JSON)', + error_message TEXT NULL COMMENT '错误信息', - CONSTRAINT FK_node_instance_workflow FOREIGN KEY (workflow_instance_id) REFERENCES wf_workflow_instance (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='节点实例表'; - --- 工作流变量表 -CREATE TABLE wf_workflow_variable ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', - create_by VARCHAR(255) NULL COMMENT '创建人', - create_time DATETIME(6) NULL COMMENT '创建时间', - deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', - update_by VARCHAR(255) NULL COMMENT '更新人', - update_time DATETIME(6) NULL COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - - workflow_instance_id BIGINT NOT NULL COMMENT '工作流实例ID', - name VARCHAR(100) NOT NULL COMMENT '变量名', - value TEXT NULL COMMENT '变量值', - type VARCHAR(20) NOT NULL COMMENT '变量类型', - - CONSTRAINT FK_workflow_variable_instance FOREIGN KEY (workflow_instance_id) REFERENCES wf_workflow_instance (id), - CONSTRAINT UK_workflow_variable_instance_name UNIQUE (workflow_instance_id, name) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流变量表'; + CONSTRAINT FK_workflow_node_instance_instance FOREIGN KEY (workflow_instance_id) REFERENCES workflow_instance(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流节点实例表'; -- 工作流日志表 -CREATE TABLE wf_log ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - workflow_instance_id BIGINT NOT NULL COMMENT '工作流实例ID', - node_id VARCHAR(50) NULL COMMENT '节点ID', - level VARCHAR(10) NOT NULL COMMENT '日志级别', - message TEXT NOT NULL COMMENT '日志内容', - detail TEXT, - create_time DATETIME NOT NULL, - create_by VARCHAR(50), - update_time DATETIME, - update_by VARCHAR(50), - version INT DEFAULT 0, - deleted BOOLEAN DEFAULT FALSE, - CONSTRAINT FK_workflow_log_instance FOREIGN KEY (workflow_instance_id) REFERENCES wf_workflow_instance (id) -); - --- 创建索引 -CREATE INDEX idx_wf_workflow_variable_instance ON wf_workflow_variable (workflow_instance_id); -CREATE INDEX idx_wf_log_instance ON wf_log (workflow_instance_id); -CREATE INDEX idx_wf_log_node ON wf_log (workflow_instance_id, node_id); - --- 工作流权限表 -CREATE TABLE wf_workflow_permission ( - id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', - workflow_definition_id BIGINT NOT NULL COMMENT '工作流定义ID', - type VARCHAR(50) NOT NULL COMMENT '权限类型', - user_id BIGINT COMMENT '用户ID', - role_id BIGINT COMMENT '角色ID', - department_id BIGINT COMMENT '部门ID', - create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - create_by BIGINT NOT NULL COMMENT '创建人', - update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - update_by BIGINT NOT NULL COMMENT '更新人', - version INT NOT NULL DEFAULT 0 COMMENT '版本号', - deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除', - INDEX idx_workflow_definition_id (workflow_definition_id), - INDEX idx_user_id (user_id), - INDEX idx_role_id (role_id), - INDEX idx_department_id (department_id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工作流权限'; - --- 节点类型表 -CREATE TABLE wf_node_type ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', - create_by VARCHAR(255) NULL COMMENT '创建人', - create_time DATETIME(6) NULL COMMENT '创建时间', - deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', - update_by VARCHAR(255) NULL COMMENT '更新人', - update_time DATETIME(6) NULL COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', +CREATE TABLE workflow_log ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', + create_by VARCHAR(255) NULL COMMENT '创建人', + create_time DATETIME(6) NULL COMMENT '创建时间', + deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除,1:已删除)', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - code VARCHAR(100) NOT NULL COMMENT '节点类型编码', - name VARCHAR(100) NOT NULL COMMENT '节点类型名称', - description TEXT NULL COMMENT '节点类型描述', - category VARCHAR(50) NOT NULL COMMENT '节点类型分类', - icon VARCHAR(100) NULL COMMENT '节点图标', - color VARCHAR(20) NULL COMMENT '节点颜色', - executors TEXT NULL COMMENT '执行器列表(JSON)', - config_schema TEXT NULL COMMENT '节点配置模式(JSON)', - default_config TEXT NULL COMMENT '默认配置(JSON)', - enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用', + workflow_instance_id BIGINT NULL COMMENT '工作流实例ID', + node_instance_id BIGINT NULL COMMENT '节点实例ID', + log_type VARCHAR(32) NOT NULL COMMENT '日志类型', + log_level VARCHAR(32) NOT NULL COMMENT '日志级别', + content TEXT NOT NULL COMMENT '日志内容', - CONSTRAINT UK_node_type_code UNIQUE (code) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='节点类型表'; \ No newline at end of file + CONSTRAINT FK_workflow_log_instance FOREIGN KEY (workflow_instance_id) REFERENCES workflow_instance(id), + CONSTRAINT FK_workflow_log_node_instance FOREIGN KEY (node_instance_id) REFERENCES workflow_node_instance(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流日志表'; diff --git a/backend/src/main/resources/db/migration/V1.0.1__init_data.sql b/backend/src/main/resources/db/migration/V1.0.1__init_data.sql index e7270d1c..6c69bdee 100644 --- a/backend/src/main/resources/db/migration/V1.0.1__init_data.sql +++ b/backend/src/main/resources/db/migration/V1.0.1__init_data.sql @@ -154,390 +154,4 @@ INSERT INTO sys_external_system ( -- -------------------------------------------------------------------------------------- -- 初始化工作流相关数据 --- -------------------------------------------------------------------------------------- - --- 初始化工作流定义 -INSERT INTO wf_workflow_definition ( - id, create_by, create_time, deleted, update_by, update_time, version, - code, name, description, status, version_no, node_config, transition_config, form_definition, graph_definition, enabled -) VALUES ( - 1, 'admin', NOW(), 0, 'admin', NOW(), 0, - 'DEPLOY_WORKFLOW', '标准部署流程', '标准的应用部署流程,包含代码拉取、编译构建、部署等步骤', - 1, 1, - '{"startNode":{"type":"START","name":"开始"},"endNode":{"type":"END","name":"结束"},"taskNodes":[{"id":"build","type":"TASK","name":"构建"},{"id":"deploy","type":"TASK","name":"部署"}]}', - '{"transitions":[{"from":"startNode","to":"build"},{"from":"build","to":"deploy"},{"from":"deploy","to":"endNode"}]}', - '{"fields":[{"name":"appName","label":"应用名称","type":"input","required":true},{"name":"branch","label":"分支","type":"select","required":true}]}', - '{"nodes":[{"id":"startNode","type":"START","x":100,"y":100},{"id":"build","type":"TASK","x":300,"y":100},{"id":"deploy","type":"TASK","x":500,"y":100},{"id":"endNode","type":"END","x":700,"y":100}],"edges":[{"source":"startNode","target":"build"},{"source":"build","target":"deploy"},{"source":"deploy","target":"endNode"}]}', - 1 -); - --- 初始化工作流实例 -INSERT INTO wf_workflow_instance ( - id, create_by, create_time, deleted, update_by, update_time, version, - workflow_definition_id, business_key, status, start_time, end_time, error -) VALUES ( - 1, 'admin', NOW(), 0, 'admin', NOW(), 0, - 1, 'TEST-APP-001', 2, - NOW(), NULL, NULL -); - --- 初始化节点实例 -INSERT INTO wf_node_instance ( - id, create_by, create_time, deleted, update_by, update_time, version, - workflow_instance_id, node_id, node_type, name, status, start_time, end_time, config, input, output, error, pre_node_id -) VALUES --- 开始节点实例 -(1, 'admin', NOW(), 0, 'admin', NOW(), 0, - 1, 'startNode', 0, '开始', 3, - DATE_SUB(NOW(), INTERVAL 5 MINUTE), DATE_SUB(NOW(), INTERVAL 4 MINUTE), - '{"type":"START","name":"开始"}', - '{"appName":"test-app","branch":"master"}', '{}', NULL, NULL), --- 构建节点实例 -(2, 'admin', NOW(), 0, 'admin', NOW(), 0, - 1, 'build', 2, '构建', 2, - DATE_SUB(NOW(), INTERVAL 3 MINUTE), NULL, - '{"type":"TASK","name":"构建","executor":"JENKINS","jenkinsJob":"app-build"}', - '{"appName":"test-app","branch":"master"}', NULL, NULL, 'startNode'), --- 部署节点实例 -(3, 'admin', NOW(), 0, 'admin', NOW(), 0, - 1, 'deploy', 2, '部署', 1, - DATE_SUB(NOW(), INTERVAL 2 MINUTE), NULL, - '{"type":"TASK","name":"部署","executor":"SHELL","script":"./deploy.sh"}', - '{"appName":"test-app","branch":"master"}', NULL, NULL, 'build'), --- 结束节点实例 -(4, 'admin', NOW(), 0, 'admin', NOW(), 0, - 1, 'endNode', 1, '结束', 0, - DATE_SUB(NOW(), INTERVAL 1 MINUTE), DATE_SUB(NOW(), INTERVAL 0 MINUTE), - '{"type":"END","name":"结束"}', - '{}', '{}', NULL, 'deploy'); - --- 初始化工作流变量 -INSERT INTO wf_workflow_variable ( - id, create_by, create_time, deleted, update_by, update_time, version, - workflow_instance_id, name, value, type -) VALUES -(1, 'admin', NOW(), 0, 'admin', NOW(), 0, - 1, 'appName', 'test-app', 'STRING'), -(2, 'admin', NOW(), 0, 'admin', NOW(), 0, - 1, 'branch', 'master', 'STRING'), -(3, 'admin', NOW(), 0, 'admin', NOW(), 0, - 1, 'buildNumber', '123', 'STRING'); - --- 节点类型初始化数据 -INSERT INTO wf_node_type (id, code, name, description, category, icon, color, executors, config_schema, default_config, enabled, create_time, create_by, update_time, update_by, version, deleted) -VALUES --- 基础节点类型 -(2001, 'START', '开始节点', '工作流的开始节点', 'BASIC', 'play-circle', '#52c41a', '[]', -'{ - "type": "object", - "properties": { - "name": { - "type": "string", - "title": "节点名称", - "minLength": 1, - "maxLength": 50 - }, - "description": { - "type": "string", - "title": "节点描述", - "maxLength": 200 - } - }, - "required": ["name"] -}', -'{"name": "开始", "description": ""}', -true, NOW(), 'system', NOW(), 'system', 1, false), - -(2002, 'END', '结束节点', '工作流的结束节点', 'BASIC', 'stop', '#ff4d4f', '[]', -'{ - "type": "object", - "properties": { - "name": { - "type": "string", - "title": "节点名称", - "minLength": 1, - "maxLength": 50 - }, - "description": { - "type": "string", - "title": "节点描述", - "maxLength": 200 - } - }, - "required": ["name"] -}', -'{"name": "结束", "description": ""}', -true, NOW(), 'system', NOW(), 'system', 1, false), - --- 任务节点类型 -(2003, 'SCRIPT', '脚本执行节点', '执行各种脚本语言的节点', 'TASK', 'code', '#13c2c2', -'[{ - "code": "SCRIPT", - "name": "脚本执行器", - "description": "支持执行多种脚本语言(Shell、Python、JavaScript等)", - "configSchema": { - "type": "object", - "required": ["script", "language", "interpreter"], - "properties": { - "script": { - "type": "string", - "title": "脚本内容", - "format": "textarea", - "description": "需要执行的脚本内容,例如:\\n#!/bin/bash\\necho \\"开始执行脚本\\"\\nls -la\\necho \\"脚本执行完成\\"" - }, - "language": { - "type": "string", - "title": "脚本语言", - "enum": ["shell", "python", "javascript", "groovy"], - "enumNames": ["Shell脚本 (已支持)", "Python脚本 (开发中)", "JavaScript脚本 (开发中)", "Groovy脚本 (开发中)"], - "default": "shell", - "description": "脚本语言类型", - "oneOf": [ - { - "const": "shell", - "title": "Shell脚本" - }, - { - "const": "python", - "title": "Python脚本", - "readOnly": true - }, - { - "const": "javascript", - "title": "JavaScript脚本", - "readOnly": true - }, - { - "const": "groovy", - "title": "Groovy脚本", - "readOnly": true - } - ] - }, - "interpreter": { - "type": "string", - "title": "解释器路径", - "description": "脚本解释器的路径,例如:/bin/bash, /usr/bin/python3" - }, - "workingDirectory": { - "type": "string", - "title": "工作目录", - "description": "脚本执行的工作目录", - "default": "/tmp" - }, - "timeout": { - "type": "integer", - "title": "超时时间", - "description": "脚本执行的最大时间(秒)", - "minimum": 1, - "maximum": 3600, - "default": 300 - }, - "retryTimes": { - "type": "integer", - "title": "重试次数", - "minimum": 0, - "maximum": 10, - "default": 0 - }, - "retryInterval": { - "type": "integer", - "title": "重试间隔(秒)", - "minimum": 1, - "maximum": 3600, - "default": 60 - }, - "environment": { - "type": "object", - "title": "环境变量", - "description": "脚本执行时的环境变量", - "additionalProperties": { - "type": "string" - } - }, - "successExitCode": { - "type": "integer", - "title": "成功退出码", - "description": "脚本执行成功时的退出码", - "default": 0 - }, - "supportedLanguages": { - "type": "array", - "title": "支持的脚本语言", - "items": { - "type": "string", - "enum": ["shell", "python", "javascript", "groovy"] - }, - "default": ["shell"] - } - } - } -}]', -'{ - "type": "object", - "required": ["name", "executor"], - "properties": { - "name": { - "type": "string", - "title": "节点名称", - "minLength": 1, - "maxLength": 50 - }, - "description": { - "type": "string", - "title": "节点描述", - "maxLength": 200 - }, - "executor": { - "type": "string", - "title": "执行器", - "enum": ["SCRIPT"], - "enumNames": ["脚本执行器"] - } - } -}', -'{"name": "脚本执行", "executor": "SCRIPT"}', -true, NOW(), 'system', NOW(), 'system', 1, false), - --- Git节点类型 -(2004, 'GIT', 'Git操作节点', '执行Git操作的任务节点', 'TASK', 'branch', '#722ed1', -'[{ - "code": "GIT", - "name": "Git操作执行器", - "description": "执行Git操作,支持克隆、拉取、切换分支等操作", - "configSchema": { - "type": "object", - "required": ["operation", "repository"], - "properties": { - "operation": { - "type": "string", - "title": "Git操作", - "enum": ["CLONE", "PULL", "CHECKOUT", "FETCH"], - "enumNames": ["克隆仓库", "拉取代码", "切换分支", "获取更新"], - "description": "要执行的Git操作类型" - }, - "repository": { - "type": "string", - "title": "仓库地址", - "description": "Git仓库的URL地址" - }, - "branch": { - "type": "string", - "title": "分支名称", - "description": "Git分支名称", - "default": "master" - }, - "workingDirectory": { - "type": "string", - "title": "工作目录", - "description": "Git操作的工作目录", - "default": "/tmp" - }, - "timeout": { - "type": "number", - "title": "超时时间", - "description": "操作的最大执行时间(秒)", - "minimum": 1, - "maximum": 3600, - "default": 300 - }, - "credentials": { - "type": "object", - "title": "认证信息", - "properties": { - "username": { - "type": "string", - "title": "用户名" - }, - "password": { - "type": "string", - "title": "密码/Token", - "format": "password" - } - } - } - } - } -}]', -'{ - "type": "object", - "properties": { - "name": { - "type": "string", - "title": "节点名称", - "minLength": 1, - "maxLength": 50 - }, - "description": { - "type": "string", - "title": "节点描述", - "maxLength": 200 - }, - "executor": { - "type": "string", - "title": "执行器", - "enum": ["GIT"], - "enumNames": ["Git操作执行器"] - } - }, - "required": ["name", "executor"] -}', -'{"name": "Git操作", "executor": "GIT"}', -true, NOW(), 'system', NOW(), 'system', 1, false), - --- 网关节点类型 -(2005, 'GATEWAY', '网关节点', '控制流程流转的网关节点', 'GATEWAY', 'fork', '#faad14', '[]', -'{ - "type": "object", - "properties": { - "name": { - "type": "string", - "title": "节点名称", - "minLength": 1, - "maxLength": 50 - }, - "description": { - "type": "string", - "title": "节点描述", - "maxLength": 200 - }, - "type": { - "type": "string", - "title": "网关类型", - "enum": ["PARALLEL", "EXCLUSIVE", "INCLUSIVE"], - "enumNames": ["并行网关", "排他网关", "包容网关"] - } - }, - "required": ["name", "type"] -}', -'{"name": "网关", "type": "EXCLUSIVE"}', -true, NOW(), 'system', NOW(), 'system', 1, false), - --- 事件节点类型 -(2006, 'TIMER', '定时器节点', '定时触发的事件节点', 'EVENT', 'clock-circle', '#722ed1', '[]', -'{ - "type": "object", - "properties": { - "name": { - "type": "string", - "title": "节点名称", - "minLength": 1, - "maxLength": 50 - }, - "description": { - "type": "string", - "title": "节点描述", - "maxLength": 200 - }, - "cron": { - "type": "string", - "title": "CRON表达式", - "description": "定时触发的CRON表达式(秒 分 时 日 月 周)", - "pattern": "^\\s*($|[0-9\\-*/,]+\\s+[0-9\\-*/,]+\\s+[0-9\\-*/,]+\\s+[0-9\\-*/,]+\\s+[0-9\\-*/,]+\\s+[0-9\\-*/,?]+)\\s*$", - "examples": ["0 0 * * * ?", "0 0/5 * * * ?", "0 0 8 * * ?"] - } - }, - "required": ["name", "cron"] -}', -'{"name": "定时器", "cron": "0 0 * * * ?"}', -true, NOW(), 'system', NOW(), 'system', 1, false); \ No newline at end of file +-- -------------------------------------------------------------------------------------- \ No newline at end of file