1202 lines
35 KiB
Markdown
1202 lines
35 KiB
Markdown
# Deploy Ease 自动化部署平台设计文档
|
||
|
||
## 一、系统概述
|
||
|
||
### 1.1 功能模块
|
||
1. 项目集管理
|
||
- 项目集配置
|
||
- 项目管理
|
||
- Git仓库集成
|
||
- Jenkins集成
|
||
|
||
2. 环境管理
|
||
- 环境配置
|
||
- 环境克隆
|
||
- 环境变量管理
|
||
- 权限控制
|
||
|
||
3. 工作流引擎
|
||
- 流程设计
|
||
- 节点执行
|
||
- 状态管理
|
||
- 日志追踪
|
||
|
||
4. 审批流程
|
||
- 审批配置
|
||
- 审批执行
|
||
- 权限管理
|
||
- 日志记录
|
||
|
||
5. 配置中心
|
||
- Nacos配置管理
|
||
- 配置同步
|
||
- 版本控制
|
||
- 变更追踪
|
||
|
||
## 二、数据库设计
|
||
|
||
### 2.1 项目管理相关表
|
||
```sql
|
||
-- 项目集表
|
||
CREATE TABLE sys_project_group (
|
||
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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
code VARCHAR(50) NOT NULL COMMENT '项目集编码',
|
||
name VARCHAR(100) NOT NULL COMMENT '项目集名称',
|
||
description TEXT COMMENT '描述',
|
||
git_group_url VARCHAR(255) NOT NULL COMMENT 'Git组地址',
|
||
jenkins_folder VARCHAR(255) COMMENT 'Jenkins文件夹',
|
||
deploy_type VARCHAR(20) NOT NULL COMMENT '部署类型:JENKINS/SELF_BUILD',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ENABLED' COMMENT '状态:ENABLED/DISABLED',
|
||
|
||
CONSTRAINT uk_group_code UNIQUE (tenant_id, code),
|
||
CONSTRAINT uk_group_name UNIQUE (tenant_id, name)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目集表';
|
||
|
||
-- 项目表
|
||
CREATE TABLE sys_project (
|
||
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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
group_id BIGINT NOT NULL COMMENT '项目集ID',
|
||
code VARCHAR(50) NOT NULL COMMENT '项目编码',
|
||
name VARCHAR(100) NOT NULL COMMENT '项目名称',
|
||
description TEXT COMMENT '描述',
|
||
git_url VARCHAR(255) NOT NULL COMMENT 'Git地址',
|
||
jenkins_job VARCHAR(255) COMMENT 'Jenkins任务名',
|
||
build_type VARCHAR(20) NOT NULL COMMENT '构建类型:MAVEN/GRADLE/NPM',
|
||
enable_build BIT NOT NULL DEFAULT 1 COMMENT '是否启用构建',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ENABLED' COMMENT '状态:ENABLED/DISABLED',
|
||
|
||
CONSTRAINT fk_project_group FOREIGN KEY (group_id) REFERENCES sys_project_group(id),
|
||
CONSTRAINT uk_project_code UNIQUE (tenant_id, code),
|
||
CONSTRAINT uk_project_name UNIQUE (tenant_id, group_id, name)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目表';
|
||
```
|
||
|
||
### 2.2 环境管理相关表
|
||
```sql
|
||
-- 环境表
|
||
CREATE TABLE sys_environment (
|
||
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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
code VARCHAR(50) NOT NULL COMMENT '环境编码',
|
||
name VARCHAR(100) NOT NULL COMMENT '环境名称',
|
||
description TEXT COMMENT '描述',
|
||
type VARCHAR(20) NOT NULL COMMENT '环境类型:DEV/TEST/UAT/PROD',
|
||
need_approval BIT NOT NULL DEFAULT 0 COMMENT '是否需要审批',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ENABLED' COMMENT '状态:ENABLED/DISABLED',
|
||
|
||
CONSTRAINT uk_env_code UNIQUE (tenant_id, code),
|
||
CONSTRAINT uk_env_name UNIQUE (tenant_id, name)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='环境表';
|
||
|
||
-- 项目环境配置表
|
||
CREATE TABLE sys_project_env (
|
||
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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
project_id BIGINT NOT NULL COMMENT '项目ID',
|
||
env_id BIGINT NOT NULL COMMENT '环境ID',
|
||
workflow_id BIGINT COMMENT '工作流定义ID',
|
||
config TEXT COMMENT '环境配置(JSON)',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ENABLED' COMMENT '状态:ENABLED/DISABLED',
|
||
|
||
CONSTRAINT fk_env_project FOREIGN KEY (project_id) REFERENCES sys_project(id),
|
||
CONSTRAINT fk_env_environment FOREIGN KEY (env_id) REFERENCES sys_environment(id),
|
||
CONSTRAINT uk_project_env UNIQUE (tenant_id, project_id, env_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目环境配置表';
|
||
```
|
||
|
||
### 2.3 工作流相关表
|
||
```sql
|
||
-- 工作流定义表
|
||
CREATE TABLE sys_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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
code VARCHAR(50) NOT NULL COMMENT '工作流编码',
|
||
name VARCHAR(100) NOT NULL COMMENT '工作流名称',
|
||
description TEXT COMMENT '描述',
|
||
content TEXT NOT NULL COMMENT '工作流定义(JSON)',
|
||
type VARCHAR(20) NOT NULL COMMENT '类型:DEPLOY/CONFIG_SYNC',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'DRAFT' COMMENT '状态:DRAFT/PUBLISHED/DISABLED',
|
||
|
||
CONSTRAINT uk_workflow_code UNIQUE (tenant_id, code)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流定义表';
|
||
|
||
-- 工作流实例表
|
||
CREATE TABLE sys_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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
definition_id BIGINT NOT NULL COMMENT '工作流定义ID',
|
||
project_env_id BIGINT NOT NULL COMMENT '项目环境ID',
|
||
status VARCHAR(20) NOT NULL COMMENT '状态:RUNNING/COMPLETED/FAILED/CANCELED',
|
||
start_time DATETIME NOT NULL COMMENT '开始时间',
|
||
end_time DATETIME COMMENT '结束时间',
|
||
variables TEXT COMMENT '工作流变量(JSON)',
|
||
error TEXT COMMENT '错误信息',
|
||
|
||
CONSTRAINT fk_instance_definition FOREIGN KEY (definition_id) REFERENCES sys_workflow_definition(id),
|
||
CONSTRAINT fk_instance_project_env FOREIGN KEY (project_env_id) REFERENCES sys_project_env(id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流实例表';
|
||
|
||
-- 节点实例表
|
||
CREATE TABLE sys_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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
workflow_instance_id BIGINT NOT NULL COMMENT '工作流实例ID',
|
||
node_id VARCHAR(50) NOT NULL COMMENT '节点ID',
|
||
node_type VARCHAR(50) NOT NULL COMMENT '节点类型',
|
||
name VARCHAR(100) NOT NULL COMMENT '节点名称',
|
||
status VARCHAR(20) NOT NULL COMMENT '状态:PENDING/RUNNING/COMPLETED/FAILED/CANCELED',
|
||
start_time DATETIME COMMENT '开始时间',
|
||
end_time DATETIME COMMENT '结束时间',
|
||
input TEXT COMMENT '输入参数(JSON)',
|
||
output TEXT COMMENT '输出结果(JSON)',
|
||
error TEXT COMMENT '错误信息',
|
||
|
||
CONSTRAINT fk_node_workflow_instance FOREIGN KEY (workflow_instance_id) REFERENCES sys_workflow_instance(id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='节点实例表';
|
||
```
|
||
|
||
### 2.4 审批相关表
|
||
```sql
|
||
-- 审批流程定义表
|
||
CREATE TABLE sys_approval_flow (
|
||
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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
code VARCHAR(50) NOT NULL COMMENT '流程编码',
|
||
name VARCHAR(100) NOT NULL COMMENT '流程名称',
|
||
description TEXT COMMENT '描述',
|
||
type VARCHAR(20) NOT NULL COMMENT '流程类型:DEPLOY/LEAVE/NACOS_CONFIG',
|
||
content TEXT NOT NULL COMMENT '流程定义(JSON)',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ENABLED' COMMENT '状态:ENABLED/DISABLED',
|
||
|
||
CONSTRAINT uk_flow_code UNIQUE (tenant_id, code)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审批流程定义表';
|
||
|
||
-- 审批任务表
|
||
CREATE TABLE sys_approval_task (
|
||
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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
flow_id BIGINT NOT NULL COMMENT '流程定义ID',
|
||
node_id BIGINT NOT NULL COMMENT '当前节点ID',
|
||
title VARCHAR(200) NOT NULL COMMENT '审批标题',
|
||
status VARCHAR(20) NOT NULL COMMENT '状态:PENDING/APPROVED/REJECTED/CANCELED',
|
||
start_time DATETIME NOT NULL COMMENT '开始时间',
|
||
end_time DATETIME COMMENT '结束时间',
|
||
variables TEXT COMMENT '审批变量(JSON)',
|
||
|
||
CONSTRAINT fk_task_flow FOREIGN KEY (flow_id) REFERENCES sys_approval_flow(id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审批任务表';
|
||
|
||
-- 审批记录表
|
||
CREATE TABLE sys_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 '是否删除',
|
||
update_by VARCHAR(255) NULL COMMENT '更新人',
|
||
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
tenant_id BIGINT NOT NULL COMMENT '租户ID',
|
||
|
||
task_id BIGINT NOT NULL COMMENT '审批任务ID',
|
||
node_id BIGINT NOT NULL COMMENT '审批节点ID',
|
||
approver VARCHAR(100) NOT NULL COMMENT '审批人',
|
||
action VARCHAR(20) NOT NULL COMMENT '操作:APPROVE/REJECT',
|
||
comment TEXT COMMENT '审批意见',
|
||
|
||
CONSTRAINT fk_record_task FOREIGN KEY (task_id) REFERENCES sys_approval_task(id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审批记录表';
|
||
```
|
||
|
||
## 三、API接口设计
|
||
|
||
### 3.1 项目管理接口
|
||
|
||
#### 3.1.1 项目集管理
|
||
```yaml
|
||
/api/v1/project-group:
|
||
post:
|
||
summary: 创建项目集
|
||
description: |
|
||
创建新的项目集,需要提供以下信息:
|
||
1. 项目集基本信息(编码、名称、描述)
|
||
2. Git仓库信息
|
||
3. Jenkins配置(可选)
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ProjectGroupDTO'
|
||
responses:
|
||
200:
|
||
description: 成功创建项目集
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Response'
|
||
|
||
get:
|
||
summary: 查询项目集列表
|
||
description: |
|
||
支持以下查询条件:
|
||
1. 名称模糊搜索
|
||
2. 状态过滤
|
||
3. 分页参数
|
||
parameters:
|
||
- name: name
|
||
in: query
|
||
description: 项目集名称
|
||
schema:
|
||
type: string
|
||
- name: status
|
||
in: query
|
||
description: 状态
|
||
schema:
|
||
type: string
|
||
enum: [ENABLED, DISABLED]
|
||
responses:
|
||
200:
|
||
description: 项目集列表
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PageResponse'
|
||
```
|
||
|
||
#### 3.1.2 项目管理
|
||
```yaml
|
||
/api/v1/project:
|
||
post:
|
||
summary: 创建项目
|
||
description: |
|
||
创建新项目,需要提供:
|
||
1. 项目基本信息
|
||
2. 所属项目集
|
||
3. Git仓库信息
|
||
4. 构建配置
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ProjectDTO'
|
||
responses:
|
||
200:
|
||
description: 成功创建项目
|
||
|
||
get:
|
||
summary: 查询项目列表
|
||
description: |
|
||
支持条件:
|
||
1. 项目集ID
|
||
2. 名称搜索
|
||
3. 状态过滤
|
||
parameters:
|
||
- name: groupId
|
||
in: query
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
- name: name
|
||
in: query
|
||
schema:
|
||
type: string
|
||
responses:
|
||
200:
|
||
description: 项目列表
|
||
```
|
||
|
||
### 3.2 工作流管理接口
|
||
|
||
#### 3.2.1 工作流设计
|
||
```yaml
|
||
/api/v1/workflow/definition:
|
||
post:
|
||
summary: 创建工作流
|
||
description: |
|
||
创建工作流定义,支持:
|
||
1. 节点配置
|
||
2. 连线规则
|
||
3. 变量定义
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/WorkflowDefinitionDTO'
|
||
|
||
get:
|
||
summary: 获取工作流定义
|
||
description: |
|
||
查询工作流定义,支持:
|
||
1. 基本信息
|
||
2. 节点信息
|
||
3. 连线信息
|
||
parameters:
|
||
- name: id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
```
|
||
|
||
#### 3.2.2 工作流执行
|
||
```yaml
|
||
/api/v1/workflow/instance:
|
||
post:
|
||
summary: 启动工作流
|
||
description: |
|
||
启动工作流实例,需要:
|
||
1. 工作流定义ID
|
||
2. 项目环境ID
|
||
3. 执行参数
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/WorkflowStartDTO'
|
||
|
||
get:
|
||
summary: 查询执行状态
|
||
description: |
|
||
查询工作流执行状态,包括:
|
||
1. 整体状态
|
||
2. 节点状态
|
||
3. 执行日志
|
||
parameters:
|
||
- name: id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
```
|
||
|
||
## 四、前端集成指南
|
||
|
||
### 4.1 工作流设计器
|
||
|
||
#### 4.1.1 组件结构
|
||
```typescript
|
||
// 工作流设计器组件
|
||
const WorkflowDesigner: React.FC = () => {
|
||
// 1. 画布配置
|
||
const graphConfig = {
|
||
container: 'workflow-container',
|
||
grid: true,
|
||
history: true,
|
||
connecting: {
|
||
snap: true,
|
||
allowBlank: false,
|
||
allowLoop: false,
|
||
highlight: true,
|
||
},
|
||
};
|
||
|
||
// 2. 节点配置
|
||
const nodeConfig = {
|
||
// Git同步节点
|
||
gitSync: {
|
||
width: 120,
|
||
height: 60,
|
||
attrs: {
|
||
body: {
|
||
fill: '#E7F7FF',
|
||
stroke: '#1890FF',
|
||
},
|
||
label: {
|
||
text: 'Git同步',
|
||
},
|
||
},
|
||
},
|
||
// 其他节点配置...
|
||
};
|
||
|
||
return (
|
||
<div className="workflow-designer">
|
||
<Toolbar>
|
||
<NodePalette nodes={nodeConfig} />
|
||
<div className="actions">
|
||
<Button onClick={handleSave}>保存</Button>
|
||
<Button onClick={handleDeploy}>部署</Button>
|
||
</div>
|
||
</Toolbar>
|
||
|
||
<div className="designer-container">
|
||
<div id="workflow-container" className="graph-container" />
|
||
<NodeConfig node={selectedNode} onChange={handleNodeChange} />
|
||
</div>
|
||
|
||
<LogViewer instance={currentInstance} />
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
#### 4.1.2 节点配置
|
||
```typescript
|
||
// 节点配置组件
|
||
const NodeConfig: React.FC<{node: Node}> = ({ node }) => {
|
||
// 1. 动态加载配置组件
|
||
const ConfigComponent = nodeConfigComponents[node.type];
|
||
|
||
// 2. 处理配置变更
|
||
const handleConfigChange = (config: any) => {
|
||
// 更新节点配置
|
||
node.updateConfig(config);
|
||
};
|
||
|
||
return (
|
||
<div className="node-config">
|
||
<ConfigComponent
|
||
value={node.config}
|
||
onChange={handleConfigChange}
|
||
/>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
// Git同步节点配置
|
||
const GitSyncConfig: React.FC<{value: any, onChange: (config: any) => void}> = ({
|
||
value,
|
||
onChange,
|
||
}) => {
|
||
return (
|
||
<Form layout="vertical">
|
||
<Form.Item label="分支" required>
|
||
<Input
|
||
value={value.branch}
|
||
onChange={e => onChange({ ...value, branch: e.target.value })}
|
||
/>
|
||
</Form.Item>
|
||
<Form.Item label="本地路径" required>
|
||
<Input
|
||
value={value.localPath}
|
||
onChange={e => onChange({ ...value, localPath: e.target.value })}
|
||
/>
|
||
</Form.Item>
|
||
</Form>
|
||
);
|
||
};
|
||
```
|
||
|
||
#### 4.1.3 日志查看
|
||
```typescript
|
||
// 日志查看器组件
|
||
const LogViewer: React.FC<{instance: WorkflowInstance}> = ({ instance }) => {
|
||
const [logs, setLogs] = useState<LogMessage[]>([]);
|
||
|
||
// 1. 建立WebSocket连接
|
||
useEffect(() => {
|
||
const ws = new WebSocket(`ws://localhost:8080/api/logs/${instance.id}`);
|
||
|
||
ws.onmessage = (event) => {
|
||
const log = JSON.parse(event.data);
|
||
setLogs(prev => [...prev, log]);
|
||
};
|
||
|
||
return () => ws.close();
|
||
}, [instance]);
|
||
|
||
// 2. 渲染日志
|
||
return (
|
||
<div className="log-viewer">
|
||
<Tabs>
|
||
<TabPane tab="流程日志" key="workflow">
|
||
<LogList logs={logs.filter(log => log.type === 'workflow')} />
|
||
</TabPane>
|
||
<TabPane tab="节点日志" key="node">
|
||
<LogList logs={logs.filter(log => log.type === 'node')} />
|
||
</TabPane>
|
||
</Tabs>
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
### 4.2 状态管理
|
||
|
||
#### 4.2.1 工作流状态
|
||
```typescript
|
||
// 工作流状态管理
|
||
const useWorkflowStore = create<WorkflowStore>((set) => ({
|
||
definitions: [],
|
||
instances: [],
|
||
|
||
// 加载工作流定义
|
||
loadDefinitions: async () => {
|
||
const response = await api.get('/api/v1/workflow/definition');
|
||
set({ definitions: response.data });
|
||
},
|
||
|
||
// 创建工作流实例
|
||
createInstance: async (params) => {
|
||
const response = await api.post('/api/v1/workflow/instance', params);
|
||
set(state => ({
|
||
instances: [...state.instances, response.data],
|
||
}));
|
||
},
|
||
|
||
// 更新实例状态
|
||
updateInstanceStatus: (id, status) => {
|
||
set(state => ({
|
||
instances: state.instances.map(instance =>
|
||
instance.id === id
|
||
? { ...instance, status }
|
||
: instance
|
||
),
|
||
}));
|
||
},
|
||
}));
|
||
```
|
||
|
||
#### 4.2.2 审批状态
|
||
```typescript
|
||
// 审批状态管理
|
||
const useApprovalStore = create<ApprovalStore>((set) => ({
|
||
tasks: [],
|
||
records: [],
|
||
|
||
// 加载待办任务
|
||
loadTasks: async () => {
|
||
const response = await api.get('/api/v1/approval/task');
|
||
set({ tasks: response.data });
|
||
},
|
||
|
||
// 审批通过
|
||
approve: async (taskId, comment) => {
|
||
await api.post(`/api/v1/approval/task/${taskId}/approve`, { comment });
|
||
set(state => ({
|
||
tasks: state.tasks.filter(task => task.id !== taskId),
|
||
}));
|
||
},
|
||
|
||
// 审批拒绝
|
||
reject: async (taskId, comment) => {
|
||
await api.post(`/api/v1/approval/task/${taskId}/reject`, { comment });
|
||
set(state => ({
|
||
tasks: state.tasks.filter(task => task.id !== taskId),
|
||
}));
|
||
},
|
||
}));
|
||
```
|
||
|
||
## 五、部署指南
|
||
|
||
### 5.1 环境要求
|
||
1. Java 21
|
||
2. MySQL 8.0
|
||
3. Redis 7.x
|
||
4. Node.js 18+
|
||
|
||
### 5.2 配置说明
|
||
```yaml
|
||
# application.yml
|
||
spring:
|
||
datasource:
|
||
url: jdbc:mysql://localhost:3306/deploy_ease
|
||
username: root
|
||
password: root
|
||
|
||
redis:
|
||
host: localhost
|
||
port: 6379
|
||
|
||
rabbitmq:
|
||
host: localhost
|
||
port: 5672
|
||
|
||
workflow:
|
||
executor:
|
||
core-pool-size: 10
|
||
max-pool-size: 20
|
||
queue-capacity: 100
|
||
|
||
node:
|
||
timeout: 3600 # 节点执行超时时间(秒)
|
||
retry:
|
||
max-attempts: 3
|
||
delay: 5000
|
||
```
|
||
|
||
### 5.3 部署步骤
|
||
1. 数据库初始化
|
||
```bash
|
||
mysql -u root -p deploy_ease < schema.sql
|
||
mysql -u root -p deploy_ease < data.sql
|
||
```
|
||
|
||
2. 后端部署
|
||
```bash
|
||
mvn clean package
|
||
java -jar deploy-ease.jar
|
||
```
|
||
|
||
3. 前端部署
|
||
```bash
|
||
npm install
|
||
npm run build
|
||
```
|
||
|
||
### 5.4 监控配置
|
||
1. Prometheus监控
|
||
```yaml
|
||
scrape_configs:
|
||
- job_name: 'deploy-ease'
|
||
metrics_path: '/actuator/prometheus'
|
||
static_configs:
|
||
- targets: ['localhost:8080']
|
||
```
|
||
|
||
2. Grafana面板
|
||
- JVM监控
|
||
- 接口监控
|
||
- 业务监控
|
||
|
||
# 系统优化实现
|
||
|
||
## 一、工作流引擎优化
|
||
|
||
### 1.1 增强的工作流引擎接口
|
||
```java
|
||
/**
|
||
* 增强的工作流引擎接口
|
||
*/
|
||
public interface WorkflowEngine {
|
||
// 基础功能
|
||
WorkflowInstance startWorkflow(String code, Map<String, Object> params);
|
||
void pauseWorkflow(Long instanceId);
|
||
void resumeWorkflow(Long instanceId);
|
||
void terminateWorkflow(Long instanceId, String reason);
|
||
|
||
// 批量操作支持
|
||
List<WorkflowInstance> batchStartWorkflow(List<WorkflowStartRequest> requests);
|
||
|
||
// 定时执行支持
|
||
WorkflowInstance scheduleWorkflow(String code, Map<String, Object> params, LocalDateTime executeTime);
|
||
|
||
// 条件触发支持
|
||
void registerTrigger(WorkflowTrigger trigger);
|
||
|
||
// 子流程支持
|
||
WorkflowInstance startSubWorkflow(Long parentInstanceId, String code, Map<String, Object> params);
|
||
}
|
||
|
||
/**
|
||
* 工作流触发器
|
||
*/
|
||
public interface WorkflowTrigger {
|
||
String getCode();
|
||
boolean shouldTrigger(TriggerContext context);
|
||
Map<String, Object> prepareParams(TriggerContext context);
|
||
}
|
||
```
|
||
|
||
### 1.2 工作流执行优化
|
||
```java
|
||
/**
|
||
* 优化的工作流执行器
|
||
*/
|
||
@Service
|
||
@Slf4j
|
||
public class OptimizedWorkflowExecutor {
|
||
private final ExecutorService executorService;
|
||
private final WorkflowEventBus eventBus;
|
||
private final RetryTemplate retryTemplate;
|
||
|
||
@Async
|
||
public void executeWorkflow(WorkflowInstance instance) {
|
||
MDC.put("workflowInstanceId", instance.getId().toString());
|
||
try {
|
||
// 1. 前置处理
|
||
preProcess(instance);
|
||
|
||
// 2. 并行执行支持
|
||
if (instance.isParallelExecutionEnabled()) {
|
||
executeParallel(instance);
|
||
} else {
|
||
executeSequential(instance);
|
||
}
|
||
|
||
// 3. 后置处理
|
||
postProcess(instance);
|
||
|
||
} catch (Exception e) {
|
||
handleError(instance, e);
|
||
} finally {
|
||
MDC.remove("workflowInstanceId");
|
||
}
|
||
}
|
||
|
||
private void executeParallel(WorkflowInstance instance) {
|
||
List<NodeDefinition> parallelNodes = instance.getParallelNodes();
|
||
List<Future<NodeExecuteResult>> futures = new ArrayList<>();
|
||
|
||
// 提交并行任务
|
||
for (NodeDefinition node : parallelNodes) {
|
||
futures.add(executorService.submit(() -> executeNode(instance, node)));
|
||
}
|
||
|
||
// 等待所有任务完成
|
||
for (Future<NodeExecuteResult> future : futures) {
|
||
try {
|
||
future.get(instance.getTimeout(), TimeUnit.SECONDS);
|
||
} catch (Exception e) {
|
||
handleParallelExecutionError(instance, e);
|
||
}
|
||
}
|
||
}
|
||
|
||
private NodeExecuteResult executeNode(WorkflowInstance instance, NodeDefinition node) {
|
||
return retryTemplate.execute(context -> {
|
||
NodeExecutor executor = getExecutor(node);
|
||
return executor.execute(createContext(instance, node));
|
||
});
|
||
}
|
||
}
|
||
```
|
||
|
||
## 二、节点执行优化
|
||
|
||
### 2.1 增强的节点上下文
|
||
```java
|
||
/**
|
||
* 增强的节点上下文
|
||
*/
|
||
public interface NodeContext {
|
||
// 基础功能
|
||
String getNodeId();
|
||
<T> T getNodeConfig(Class<T> clazz);
|
||
Map<String, Object> getVariables();
|
||
NodeLogger getLogger();
|
||
|
||
// 数据传递
|
||
void setVariable(String key, Object value);
|
||
void setTransientVariable(String key, Object value);
|
||
|
||
// 条件判断
|
||
boolean evaluateCondition(String expression);
|
||
|
||
// 重试策略
|
||
RetryStrategy getRetryStrategy();
|
||
|
||
// 超时控制
|
||
Duration getTimeout();
|
||
|
||
// 回滚操作
|
||
void registerRollback(Runnable rollback);
|
||
}
|
||
|
||
/**
|
||
* 重试策略
|
||
*/
|
||
@Data
|
||
@Builder
|
||
public class RetryStrategy {
|
||
private int maxAttempts;
|
||
private Duration initialDelay;
|
||
private Duration maxDelay;
|
||
private double multiplier;
|
||
private List<Class<? extends Exception>> retryableExceptions;
|
||
}
|
||
```
|
||
|
||
### 2.2 节点执行器增强
|
||
```java
|
||
/**
|
||
* 增强的节点执行器
|
||
*/
|
||
public interface NodeExecutor {
|
||
String getType();
|
||
NodeExecuteResult execute(NodeContext context);
|
||
void cancel(NodeContext context);
|
||
|
||
// 新增方法
|
||
boolean canExecute(NodeContext context);
|
||
void validate(NodeContext context);
|
||
void prepare(NodeContext context);
|
||
void cleanup(NodeContext context);
|
||
}
|
||
|
||
/**
|
||
* 节点执行结果
|
||
*/
|
||
@Data
|
||
@Builder
|
||
public class NodeExecuteResult {
|
||
private boolean success;
|
||
private Map<String, Object> output;
|
||
private String errorMessage;
|
||
private Throwable error;
|
||
private long executionTime;
|
||
private Map<String, Object> metrics;
|
||
}
|
||
```
|
||
|
||
## 三、事件系统优化
|
||
|
||
### 3.1 事件总线实现
|
||
```java
|
||
/**
|
||
* 事件总线
|
||
*/
|
||
@Component
|
||
@Slf4j
|
||
public class WorkflowEventBus {
|
||
private final Map<String, List<WorkflowEventListener>> listeners = new ConcurrentHashMap<>();
|
||
private final ExecutorService executorService;
|
||
|
||
public void publish(WorkflowEvent event) {
|
||
String eventType = event.getType();
|
||
List<WorkflowEventListener> eventListeners = listeners.get(eventType);
|
||
|
||
if (eventListeners != null) {
|
||
// 异步处理事件
|
||
for (WorkflowEventListener listener : eventListeners) {
|
||
executorService.submit(() -> {
|
||
try {
|
||
listener.onEvent(event);
|
||
} catch (Exception e) {
|
||
log.error("Handle event failed", e);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
public void subscribe(String eventType, WorkflowEventListener listener) {
|
||
listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>())
|
||
.add(listener);
|
||
}
|
||
|
||
public void unsubscribe(String eventType, WorkflowEventListener listener) {
|
||
List<WorkflowEventListener> eventListeners = listeners.get(eventType);
|
||
if (eventListeners != null) {
|
||
eventListeners.remove(listener);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.2 事件处理器
|
||
```java
|
||
/**
|
||
* 日志事件处理器
|
||
*/
|
||
@Component
|
||
@Slf4j
|
||
public class LoggingEventHandler implements WorkflowEventListener {
|
||
|
||
@Override
|
||
public void onEvent(WorkflowEvent event) {
|
||
switch (event.getType()) {
|
||
case "WORKFLOW_START":
|
||
logWorkflowStart(event);
|
||
break;
|
||
case "WORKFLOW_END":
|
||
logWorkflowEnd(event);
|
||
break;
|
||
case "NODE_START":
|
||
logNodeStart(event);
|
||
break;
|
||
case "NODE_END":
|
||
logNodeEnd(event);
|
||
break;
|
||
default:
|
||
log.debug("Unhandled event type: {}", event.getType());
|
||
}
|
||
}
|
||
|
||
private void logWorkflowStart(WorkflowEvent event) {
|
||
WorkflowInstance instance = (WorkflowInstance) event.getPayload().get("instance");
|
||
log.info("Workflow started: {}, type: {}", instance.getId(), instance.getType());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 指标收集处理器
|
||
*/
|
||
@Component
|
||
@Slf4j
|
||
public class MetricsEventHandler implements WorkflowEventListener {
|
||
private final MeterRegistry registry;
|
||
|
||
@Override
|
||
public void onEvent(WorkflowEvent event) {
|
||
switch (event.getType()) {
|
||
case "WORKFLOW_END":
|
||
recordWorkflowMetrics(event);
|
||
break;
|
||
case "NODE_END":
|
||
recordNodeMetrics(event);
|
||
break;
|
||
}
|
||
}
|
||
|
||
private void recordWorkflowMetrics(WorkflowEvent event) {
|
||
WorkflowInstance instance = (WorkflowInstance) event.getPayload().get("instance");
|
||
Timer.builder("workflow.execution")
|
||
.tag("type", instance.getType())
|
||
.tag("status", instance.getStatus().name())
|
||
.register(registry)
|
||
.record(Duration.between(instance.getStartTime(), instance.getEndTime()));
|
||
}
|
||
}
|
||
```
|
||
|
||
## 四、插件系统优化
|
||
|
||
### 4.1 插件生命周期
|
||
```java
|
||
/**
|
||
* 插件生命周期管理
|
||
*/
|
||
public interface PluginLifecycle {
|
||
void onLoad(PluginContext context);
|
||
void onEnable();
|
||
void onDisable();
|
||
void onUnload();
|
||
}
|
||
|
||
/**
|
||
* 插件热更新支持
|
||
*/
|
||
@Component
|
||
@Slf4j
|
||
public class PluginHotLoader {
|
||
private final PluginLoader pluginLoader;
|
||
private final FileWatcher fileWatcher;
|
||
|
||
public void watchPluginDirectory(Path directory) {
|
||
fileWatcher.watch(directory, event -> {
|
||
if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) {
|
||
String jarPath = event.context().toString();
|
||
reloadPlugin(jarPath);
|
||
}
|
||
});
|
||
}
|
||
|
||
private void reloadPlugin(String jarPath) {
|
||
try {
|
||
// 1. 卸载旧插件
|
||
pluginLoader.unloadPlugin(jarPath);
|
||
|
||
// 2. 加载新插件
|
||
pluginLoader.loadPlugin(jarPath);
|
||
|
||
log.info("Plugin reloaded: {}", jarPath);
|
||
} catch (Exception e) {
|
||
log.error("Reload plugin failed: {}", jarPath, e);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.2 插件配置
|
||
```java
|
||
/**
|
||
* 插件配置管理
|
||
*/
|
||
@Component
|
||
@Slf4j
|
||
public class PluginConfigManager {
|
||
private final Map<String, PluginConfig> configs = new ConcurrentHashMap<>();
|
||
|
||
@PostConstruct
|
||
public void init() {
|
||
// 加载插件配置
|
||
loadConfigs();
|
||
|
||
// 监听配置变更
|
||
watchConfigChanges();
|
||
}
|
||
|
||
public void updateConfig(String pluginId, PluginConfig config) {
|
||
configs.put(pluginId, config);
|
||
// 通知插件配置更新
|
||
notifyConfigUpdate(pluginId, config);
|
||
}
|
||
|
||
private void notifyConfigUpdate(String pluginId, PluginConfig config) {
|
||
Plugin plugin = pluginLoader.getPlugin(pluginId);
|
||
if (plugin instanceof ConfigurablePlugin) {
|
||
((ConfigurablePlugin) plugin).onConfigUpdate(config);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 五、监控增强
|
||
|
||
### 5.1 性能监控
|
||
```java
|
||
/**
|
||
* 性能监控
|
||
*/
|
||
@Component
|
||
@Slf4j
|
||
public class PerformanceMonitor {
|
||
private final MeterRegistry registry;
|
||
|
||
// 节点执行时间分布
|
||
private final Timer nodeExecutionTimer;
|
||
|
||
// 工作流执行时间分布
|
||
private final Timer workflowExecutionTimer;
|
||
|
||
// 资源使用情况
|
||
private final Gauge threadPoolActiveThreads;
|
||
private final Gauge threadPoolQueueSize;
|
||
|
||
// 业务指标
|
||
private final Counter workflowSuccessCounter;
|
||
private final Counter workflowFailureCounter;
|
||
private final Counter nodeFailureCounter;
|
||
|
||
public void recordNodeExecution(String nodeType, long duration) {
|
||
nodeExecutionTimer.record(duration, TimeUnit.MILLISECONDS,
|
||
Tags.of("nodeType", nodeType));
|
||
}
|
||
|
||
public void recordWorkflowExecution(String workflowType, long duration) {
|
||
workflowExecutionTimer.record(duration, TimeUnit.MILLISECONDS,
|
||
Tags.of("workflowType", workflowType));
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5.2 健康检查
|
||
```java
|
||
/**
|
||
* 健康检查
|
||
*/
|
||
@Component
|
||
public class WorkflowHealthIndicator implements HealthIndicator {
|
||
private final WorkflowInstanceRepository instanceRepository;
|
||
private final NodeExecutorRegistry executorRegistry;
|
||
|
||
@Override
|
||
public Health health() {
|
||
try {
|
||
// 检查运行中的实例数
|
||
long runningInstances = instanceRepository.countByStatus(WorkflowStatus.RUNNING);
|
||
|
||
// 检查执行器状态
|
||
Map<String, Boolean> executorStatus = checkExecutors();
|
||
|
||
return Health.up()
|
||
.withDetail("runningInstances", runningInstances)
|
||
.withDetail("executorStatus", executorStatus)
|
||
.build();
|
||
|
||
} catch (Exception e) {
|
||
return Health.down()
|
||
.withException(e)
|
||
.build();
|
||
}
|
||
}
|
||
|
||
private Map<String, Boolean> checkExecutors() {
|
||
Map<String, Boolean> status = new HashMap<>();
|
||
for (NodeExecutor executor : executorRegistry.getExecutors()) {
|
||
status.put(executor.getType(), checkExecutor(executor));
|
||
}
|
||
return status;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5.3 告警配置
|
||
```java
|
||
/**
|
||
* 告警配置
|
||
*/
|
||
@Configuration
|
||
public class AlertConfig {
|
||
|
||
@Bean
|
||
public AlertManager alertManager(MeterRegistry registry) {
|
||
return AlertManager.builder()
|
||
.addRule(AlertRule.builder()
|
||
.metric("workflow.failure.count")
|
||
.threshold(5)
|
||
.duration(Duration.ofMinutes(5))
|
||
.action(this::sendAlert)
|
||
.build())
|
||
.addRule(AlertRule.builder()
|
||
.metric("node.failure.count")
|
||
.threshold(10)
|
||
.duration(Duration.ofMinutes(5))
|
||
.action(this::sendAlert)
|
||
.build())
|
||
.build();
|
||
}
|
||
|
||
private void sendAlert(Alert alert) {
|
||
// 发送告警通知
|
||
}
|
||
}
|
||
```
|
||
|
||
[保留现有的其他内容...] |