团队app配置增加绑定工作流

This commit is contained in:
dengqichen 2025-11-02 16:13:25 +08:00
parent d59d21a062
commit 87b8023e1c
10 changed files with 371 additions and 191 deletions

View File

@ -1,5 +1,7 @@
package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.deploy.dto.DeployRequestDTO;
import com.qqchen.deploy.backend.deploy.dto.DeployResultDTO;
import com.qqchen.deploy.backend.deploy.dto.UserDeployableDTO;
import com.qqchen.deploy.backend.deploy.service.IDeployService;
import com.qqchen.deploy.backend.framework.api.Response;
@ -8,9 +10,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 部署管理API控制器
@ -36,5 +38,15 @@ public class DeployApiController {
public Response<UserDeployableDTO> getDeployableEnvironments() {
return Response.success(deployService.getDeployableEnvironments());
}
/**
* 执行部署
*/
@Operation(summary = "执行部署", description = "根据团队应用配置启动部署工作流")
@PostMapping("/execute")
@PreAuthorize("isAuthenticated()")
public Response<DeployResultDTO> executeDeploy(@Validated @RequestBody DeployRequestDTO request) {
return Response.success(deployService.executeDeploy(request));
}
}

View File

@ -0,0 +1,24 @@
package com.qqchen.deploy.backend.deploy.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 部署请求DTO
*
* @author qqchen
* @since 2025-11-02
*/
@Data
@Schema(description = "部署请求")
public class DeployRequestDTO {
@Schema(description = "团队应用关联ID", required = true)
@NotNull(message = "团队应用关联ID不能为空")
private Long teamApplicationId;
@Schema(description = "部署备注")
private String remark;
}

View File

@ -0,0 +1,31 @@
package com.qqchen.deploy.backend.deploy.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 部署结果DTO
*
* @author qqchen
* @since 2025-11-02
*/
@Data
@Schema(description = "部署结果")
public class DeployResultDTO {
@Schema(description = "工作流实例ID")
private Long workflowInstanceId;
@Schema(description = "业务标识")
private String businessKey;
@Schema(description = "流程实例ID")
private String processInstanceId;
@Schema(description = "部署状态")
private String status;
@Schema(description = "提示信息")
private String message;
}

View File

@ -1,5 +1,7 @@
package com.qqchen.deploy.backend.deploy.service;
import com.qqchen.deploy.backend.deploy.dto.DeployRequestDTO;
import com.qqchen.deploy.backend.deploy.dto.DeployResultDTO;
import com.qqchen.deploy.backend.deploy.dto.UserDeployableDTO;
/**
@ -16,5 +18,13 @@ public interface IDeployService {
* @return 用户可部署环境信息
*/
UserDeployableDTO getDeployableEnvironments();
/**
* 执行部署
*
* @param request 部署请求
* @return 部署结果
*/
DeployResultDTO executeDeploy(DeployRequestDTO request);
}

View File

@ -5,10 +5,17 @@ import com.qqchen.deploy.backend.deploy.entity.*;
import com.qqchen.deploy.backend.deploy.repository.*;
import com.qqchen.deploy.backend.deploy.service.IDeployService;
import com.qqchen.deploy.backend.framework.security.SecurityUtils;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.system.entity.User;
import com.qqchen.deploy.backend.system.repository.IUserRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceDTO;
import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceStartRequest;
import com.qqchen.deploy.backend.workflow.dto.inputmapping.JenkinsBuildInputMapping;
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -56,6 +63,12 @@ public class DeployServiceImpl implements IDeployService {
@Resource
private IWorkflowDefinitionRepository workflowDefinitionRepository;
@Resource
private IWorkflowInstanceService workflowInstanceService;
@Resource
private ObjectMapper objectMapper;
@Override
@Transactional(readOnly = true)
public UserDeployableDTO getDeployableEnvironments() {
@ -388,5 +401,80 @@ public class DeployServiceImpl implements IDeployService {
return dto;
}
@Override
@Transactional
public DeployResultDTO executeDeploy(DeployRequestDTO request) {
// 1. 查询团队应用配置
TeamApplication teamApp = teamApplicationRepository.findById(request.getTeamApplicationId())
.orElseThrow(() -> new BusinessException(ResponseCode.NOT_FOUND));
// 2. 查询工作流定义获取 processKey
WorkflowDefinition workflowDefinition = workflowDefinitionRepository.findById(teamApp.getWorkflowDefinitionId())
.orElseThrow(() -> new BusinessException(ResponseCode.NOT_FOUND, new Object[]{"工作流定义"}));
// 3. 查询应用信息
Application application = applicationRepository.findById(teamApp.getApplicationId())
.orElseThrow(() -> new BusinessException(ResponseCode.NOT_FOUND, new Object[]{"应用"}));
// 4. 查询环境信息
Environment environment = environmentRepository.findById(teamApp.getEnvironmentId())
.orElseThrow(() -> new BusinessException(ResponseCode.NOT_FOUND, new Object[]{"环境"}));
// 5. 生成业务标识UUID
String businessKey = UUID.randomUUID().toString();
// 6. 构造流程变量
Map<String, Object> variables = new HashMap<>();
// 部署上下文
Map<String, Object> deployContext = new HashMap<>();
deployContext.put("teamApplicationId", teamApp.getId());
deployContext.put("teamId", teamApp.getTeamId());
deployContext.put("applicationId", teamApp.getApplicationId());
deployContext.put("applicationCode", application.getAppCode());
deployContext.put("applicationName", application.getAppName());
deployContext.put("environmentId", teamApp.getEnvironmentId());
deployContext.put("environmentCode", environment.getEnvCode());
deployContext.put("environmentName", environment.getEnvName());
deployContext.put("by", SecurityUtils.getCurrentUsername());
deployContext.put("remark", request.getRemark());
variables.put("deploy", deployContext);
// Jenkins 配置使用强类型 JenkinsBuildInputMapping
if (teamApp.getDeploySystemId() != null && teamApp.getDeployJob() != null) {
JenkinsBuildInputMapping jenkinsInput = new JenkinsBuildInputMapping();
jenkinsInput.setServerId(teamApp.getDeploySystemId());
jenkinsInput.setJobName(teamApp.getDeployJob());
if (teamApp.getBranch() != null) {
jenkinsInput.setBranch(teamApp.getBranch());
}
// 转换为 MapFlowable 只支持基本类型
variables.put("jenkins", objectMapper.convertValue(jenkinsInput, Map.class));
}
// 7. 构造工作流启动请求
WorkflowInstanceStartRequest workflowRequest = new WorkflowInstanceStartRequest();
workflowRequest.setProcessKey(workflowDefinition.getKey());
workflowRequest.setBusinessKey(businessKey);
workflowRequest.setVariables(variables);
// 8. 启动工作流
WorkflowInstanceDTO workflowInstance = workflowInstanceService.startWorkflow(workflowRequest);
log.info("部署流程已启动: businessKey={}, workflowInstanceId={}, application={}, environment={}",
businessKey, workflowInstance.getId(), application.getAppCode(), environment.getEnvCode());
// 9. 返回结果
DeployResultDTO result = new DeployResultDTO();
result.setWorkflowInstanceId(workflowInstance.getId());
result.setBusinessKey(businessKey);
result.setProcessInstanceId(workflowInstance.getProcessInstanceId());
result.setStatus(workflowInstance.getStatus().name());
result.setMessage("部署流程已启动");
return result;
}
}

View File

@ -183,6 +183,8 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
*/
protected Map<String, Object> resolveExpressions(Map<String, Object> inputMap, DelegateExecution execution) {
Map<String, Object> resolvedMap = new HashMap<>();
log.debug("开始解析 inputMap: {}", inputMap);
for (Map.Entry<String, Object> entry : inputMap.entrySet()) {
Object value = entry.getValue();
@ -193,9 +195,10 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
try {
// 使用简单的变量替换${sid_xxx.fieldName} -> 从execution中获取
String resolvedValue = resolveVariableExpression(strValue, execution);
log.debug("解析表达式: {} = {} -> {}", entry.getKey(), strValue, resolvedValue);
resolvedMap.put(entry.getKey(), resolvedValue);
} catch (Exception e) {
log.warn("Failed to resolve expression: {}, using original value", strValue);
log.warn("Failed to resolve expression: {}, using original value", strValue, e);
resolvedMap.put(entry.getKey(), value);
}
} else {
@ -205,7 +208,8 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
resolvedMap.put(entry.getKey(), value);
}
}
log.debug("解析后 resolvedMap: {}", resolvedMap);
return resolvedMap;
}
@ -239,20 +243,28 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
*/
private Object resolveVariable(String varExpression, DelegateExecution execution) {
String[] parts = varExpression.split("\\.", 2);
log.debug("解析变量表达式: {}, parts: {}", varExpression, java.util.Arrays.toString(parts));
if (parts.length == 1) {
// 直接变量${xxx}
return execution.getVariable(parts[0]);
Object result = execution.getVariable(parts[0]);
log.debug("直接变量 {} = {}", parts[0], result);
return result;
} else {
// 对象属性${sid_xxx.buildNumber}
// 对象属性${sid_xxx.buildNumber} ${jenkins.systemId}
String varName = parts[0];
String fieldName = parts[1];
Object varValue = execution.getVariable(varName);
log.debug("获取变量 {} = {}, 类型: {}", varName, varValue, varValue != null ? varValue.getClass().getName() : "null");
if (varValue instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) varValue;
return map.get(fieldName);
Object fieldValue = map.get(fieldName);
log.debug("从 Map 中获取字段 {} = {}", fieldName, fieldValue);
return fieldValue;
}
}

View File

@ -23,7 +23,7 @@ import java.util.Map;
/**
* Jenkins构建任务委派
*
*
* @author qqchen
* @since 2025-10-22
*/
@ -41,36 +41,34 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
private IJenkinsJobRepository jenkinsJobRepository;
private static final int QUEUE_POLL_INTERVAL = 10; // 10秒
private static final int MAX_QUEUE_POLLS = 30; // 最多等待5分钟
private static final int BUILD_POLL_INTERVAL = 10; // 轮询间隔
private static final int MAX_BUILD_POLLS = 180; // 30分钟超时
@Override
protected JenkinsBuildOutputs executeInternal(
DelegateExecution execution,
Map<String, Object> configs,
JenkinsBuildInputMapping input
) {
log.info("Jenkins Build - serverId: {}, jobName: {}",
input.getJenkinsServerId(), input.getProject());
protected JenkinsBuildOutputs executeInternal(DelegateExecution execution, Map<String, Object> configs, JenkinsBuildInputMapping input) {
log.info("Jenkins Build - serverId: {}, jobName: {}", input.getServerId(), input.getJobName());
// 1. 获取外部系统
ExternalSystem externalSystem = externalSystemRepository.findById(input.getJenkinsServerId().longValue())
.orElseThrow(() -> new RuntimeException("Jenkins服务器不存在: " + input.getJenkinsServerId()));
String jobName = input.getProject();
ExternalSystem externalSystem = externalSystemRepository.findById(input.getServerId())
.orElseThrow(() -> new RuntimeException("Jenkins服务器不存在: " + input.getServerId()));
String jobName = input.getJobName();
// 2. 触发构建
Map<String, String> parameters = new HashMap<>();
// 可以根据需要添加构建参数
// parameters.put("BRANCH", "main");
String queueId = jenkinsServiceIntegration.buildWithParameters(
externalSystem, jobName, parameters);
// 3. 等待构建从队列中开始
JenkinsQueueBuildInfoResponse buildInfo = waitForBuildToStart(queueId);
// 4. 轮询构建状态直到完成
// 注意如果构建失败或被取消pollBuildStatus 会抛出 BpmnError触发错误边界事件
// 只有成功时才会返回到这里
@ -80,23 +78,23 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
JenkinsBuildResponse buildDetails = jenkinsServiceIntegration.getBuildDetails(externalSystem, jobName, buildInfo.getBuildNumber());
// 打印调试信息
log.info("Build details - changeSets: {}, artifacts: {}",
log.info("Build details - changeSets: {}, artifacts: {}",
buildDetails.getChangeSets(), buildDetails.getArtifacts());
// 6. 构造输出结果执行到这里说明构建成功
JenkinsBuildOutputs outputs = new JenkinsBuildOutputs();
// 设置统一的执行状态为成功
outputs.setStatus(NodeExecutionStatusEnum.SUCCESS);
// 设置 Jenkins 特有字段
outputs.setBuildStatus(buildStatus.name());
outputs.setBuildNumber(buildInfo.getBuildNumber());
outputs.setBuildUrl(buildInfo.getBuildUrl());
// 从构建详情中提取信息
outputs.setBuildDuration(buildDetails.getDuration() != null ? buildDetails.getDuration().intValue() : 0);
// 提取 Git Commit ID changeSets 中获取第一个
if (buildDetails.getChangeSets() != null && !buildDetails.getChangeSets().isEmpty()) {
log.info("Found {} changeSets", buildDetails.getChangeSets().size());
@ -111,7 +109,7 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
if (outputs.getGitCommitId() == null) {
outputs.setGitCommitId("");
}
// 提取构建制品URL如果有多个制品拼接成逗号分隔的列表
if (buildDetails.getArtifacts() != null && !buildDetails.getArtifacts().isEmpty()) {
log.info("Found {} artifacts", buildDetails.getArtifacts().size());
@ -123,7 +121,7 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
log.warn("No artifacts found in build details");
outputs.setArtifactUrl("");
}
return outputs;
}
@ -168,11 +166,11 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
return status;
case FAILURE:
// 构建失败抛出错误触发边界事件
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR,
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR,
String.format("Jenkins build failed: job=%s, buildNumber=%d", jobName, buildNumber));
case ABORTED:
// 构建被取消抛出错误触发边界事件
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR,
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR,
String.format("Jenkins build was aborted: job=%s, buildNumber=%d", jobName, buildNumber));
case IN_PROGRESS:
// 继续轮询
@ -180,7 +178,7 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
break;
case NOT_FOUND:
// 构建记录丢失抛出系统异常
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR,
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR,
String.format("Jenkins build not found: job=%s, buildNumber=%d", jobName, buildNumber));
}
} catch (InterruptedException e) {
@ -189,8 +187,8 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
}
}
// 超过最大轮询次数视为超时系统异常
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR,
String.format("Jenkins build timed out after %d minutes: job=%s, buildNumber=%d",
throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR,
String.format("Jenkins build timed out after %d minutes: job=%s, buildNumber=%d",
MAX_BUILD_POLLS * BUILD_POLL_INTERVAL / 60, jobName, buildNumber));
}
}

View File

@ -14,17 +14,23 @@ import jakarta.validation.constraints.NotBlank;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class JenkinsBuildInputMapping {
/**
* Jenkins服务器ID
*/
@NotNull(message = "Jenkins服务器ID不能为空")
private Integer jenkinsServerId;
private Long serverId;
/**
* 项目名称
*/
@NotBlank(message = "项目名称不能为空")
private String project;
private String jobName;
/**
* 项目分支
*/
@NotBlank(message = "项目分支不能为空")
private String branch;
}

View File

@ -173,12 +173,11 @@ public class WorkflowInstanceServiceImpl extends BaseServiceImpl<WorkflowInstanc
.orElseThrow(() -> new RuntimeException("Workflow definition not found: " + request.getProcessKey()));
// 2. 获取流程变量如果没有则使用空 Map
Map<String, Object> variables = request.getVariables() != null ? request.getVariables() : new HashMap<>();
// 3. 启动 Flowable 流程
ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
.processDefinitionKey(request.getProcessKey())
.variables(variables)
.variables(request.getVariables())
.businessKey(request.getBusinessKey())
.startAsync(); // 异步启动会自动执行任务

View File

@ -5,23 +5,23 @@
-- 租户表
CREATE TABLE sys_tenant
(
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(255) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
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 '更新时间',
update_by VARCHAR(255) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
code VARCHAR(50) NOT NULL COMMENT '租户编码',
name VARCHAR(100) NOT NULL COMMENT '租户名称',
address VARCHAR(255) NULL COMMENT '租户地址',
contact_name VARCHAR(50) NULL COMMENT '联系人姓名',
contact_phone VARCHAR(20) NULL COMMENT '联系人电话',
email VARCHAR(100) NULL COMMENT '联系人邮箱',
name VARCHAR(100) NOT NULL COMMENT '租户名称',
address VARCHAR(255) NULL COMMENT '租户地址',
contact_name VARCHAR(50) NULL COMMENT '联系人姓名',
contact_phone VARCHAR(20) NULL COMMENT '联系人电话',
email VARCHAR(100) NULL COMMENT '联系人邮箱',
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用0禁用1启用',
CONSTRAINT UK_tenant_code UNIQUE (code)
CONSTRAINT UK_tenant_code UNIQUE (code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='租户表';
@ -64,10 +64,10 @@ CREATE TABLE sys_user
nickname VARCHAR(50) NULL COMMENT '昵称',
email VARCHAR(100) NULL COMMENT '邮箱',
phone VARCHAR(20) NULL COMMENT '手机号',
department_id BIGINT NULL COMMENT '所属部门ID',
department_id BIGINT NULL COMMENT '所属部门ID',
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用0禁用1启用',
CONSTRAINT UK_user_username UNIQUE (username),
CONSTRAINT UK_user_username UNIQUE (username),
CONSTRAINT FK_user_department FOREIGN KEY (department_id) REFERENCES sys_department (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
@ -249,7 +249,7 @@ CREATE TABLE sys_role_permission
(
role_id BIGINT NOT NULL COMMENT '角色ID',
permission_id BIGINT NOT NULL COMMENT '权限ID',
PRIMARY KEY (role_id, permission_id),
CONSTRAINT FK_role_permission_role FOREIGN KEY (role_id) REFERENCES sys_role (id),
CONSTRAINT FK_role_permission_permission FOREIGN KEY (permission_id) REFERENCES sys_permission (id)
@ -387,23 +387,23 @@ CREATE TABLE deploy_repo_branch
-- 工作流分类表
CREATE TABLE workflow_category
(
-- 主键
-- 主键
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
-- 基础信息
-- 基础信息
name VARCHAR(100) NOT NULL COMMENT '分类名称',
code VARCHAR(50) NOT NULL COMMENT '分类编码唯一如SCRIPT_EXECUTION',
description VARCHAR(500) NULL COMMENT '分类描述',
icon VARCHAR(50) NULL COMMENT '图标',
sort INT NOT NULL DEFAULT 0 COMMENT '排序',
-- 支持的触发方式JSON数组如["MANUAL","SCHEDULED"]
-- 支持的触发方式JSON数组如["MANUAL","SCHEDULED"]
supported_triggers JSON NULL COMMENT '支持的触发方式列表',
-- 状态
-- 状态
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
-- 审计字段
-- 审计字段
create_by VARCHAR(255) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
@ -411,8 +411,8 @@ CREATE TABLE workflow_category
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
-- 约束和索引
UNIQUE KEY uk_code (code),
-- 约束和索引
UNIQUE KEY uk_code (code),
INDEX idx_enabled (enabled),
INDEX idx_deleted (deleted),
INDEX idx_sort (sort)
@ -421,20 +421,20 @@ CREATE TABLE workflow_category
CREATE TABLE form_category
(
-- 主键
-- 主键
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
-- 基础信息
-- 基础信息
name VARCHAR(100) NOT NULL COMMENT '分类名称',
code VARCHAR(50) NOT NULL COMMENT '分类编码(唯一)',
description VARCHAR(500) NULL COMMENT '分类描述',
icon VARCHAR(50) NULL COMMENT '图标',
sort INT NOT NULL DEFAULT 0 COMMENT '排序',
-- 状态
-- 状态
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
-- 审计字段
-- 审计字段
create_by VARCHAR(255) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
@ -442,8 +442,8 @@ CREATE TABLE form_category
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
-- 约束和索引
UNIQUE KEY uk_code (code),
-- 约束和索引
UNIQUE KEY uk_code (code),
INDEX idx_enabled (enabled),
INDEX idx_deleted (deleted),
INDEX idx_sort (sort)
@ -453,25 +453,25 @@ CREATE TABLE form_category
-- 表单定义表
CREATE TABLE form_definition
(
-- 主键
-- 主键
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
-- 基础信息
-- 基础信息
name VARCHAR(255) NOT NULL COMMENT '表单名称',
`key` VARCHAR(255) NOT NULL COMMENT '表单标识(业务唯一)',
form_version INT NOT NULL DEFAULT 1 COMMENT '表单版本号',
category_id BIGINT NULL COMMENT '表单分类ID外键关联form_category',
description TEXT NULL COMMENT '表单描述',
-- 表单配置
-- 表单配置
`schema` JSON NOT NULL COMMENT '表单Schema前端设计器导出的JSON结构',
tags JSON NULL COMMENT '标签(用于分类和搜索)',
-- 表单属性
-- 表单属性
status VARCHAR(50) NOT NULL DEFAULT 'DRAFT' COMMENT '状态DRAFT-草稿、PUBLISHED-已发布、DISABLED-已禁用)',
is_template BIT NULL DEFAULT 0 COMMENT '是否为模板',
-- 审计字段
-- 审计字段
create_by VARCHAR(255) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
@ -479,14 +479,14 @@ CREATE TABLE form_definition
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
-- 约束和索引
UNIQUE KEY uk_key_version (`key`, form_version),
-- 约束和索引
UNIQUE KEY uk_key_version (`key`, form_version),
INDEX idx_category_id (category_id),
INDEX idx_status (status),
INDEX idx_is_template (is_template),
INDEX idx_deleted (deleted),
-- 外键约束
-- 外键约束
CONSTRAINT fk_form_definition_category FOREIGN KEY (category_id) REFERENCES form_category (id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci
COMMENT = '表单定义表';
@ -563,31 +563,31 @@ CREATE TABLE workflow_node_definition
-- 表单数据表
CREATE TABLE form_data
(
-- 主键
-- 主键
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
-- 关联表单定义
-- 关联表单定义
form_definition_id BIGINT NOT NULL COMMENT '表单定义ID',
form_key VARCHAR(255) NOT NULL COMMENT '表单标识冗余存储避免JOIN',
form_version INT NOT NULL COMMENT '表单版本(冗余存储,用于历史追溯)',
category_id BIGINT NULL COMMENT '表单分类ID冗余存储便于统计和查询',
-- 业务关联(松耦合)
-- 业务关联(松耦合)
business_key VARCHAR(255) NULL COMMENT '业务标识如工作流实例ID、订单号等',
business_type VARCHAR(50) NULL COMMENT '业务类型WORKFLOW-工作流、ORDER-订单、STANDALONE-独立表单)',
-- 表单数据
-- 表单数据
data JSON NOT NULL COMMENT '表单填写数据(用户提交的实际数据)',
schema_snapshot JSON NOT NULL COMMENT '表单Schema快照用于历史追溯确保数据可还原',
-- 提交信息
-- 提交信息
submitter VARCHAR(255) NULL COMMENT '提交人',
submit_time DATETIME(6) NULL COMMENT '提交时间',
-- 状态
-- 状态
status VARCHAR(50) NOT NULL DEFAULT 'SUBMITTED' COMMENT '状态DRAFT-草稿、SUBMITTED-已提交、COMPLETED-已完成、REJECTED-已拒绝)',
-- 审计字段
-- 审计字段
create_by VARCHAR(255) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
@ -595,7 +595,7 @@ CREATE TABLE form_data
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
-- 索引
-- 索引
INDEX idx_form_definition_id (form_definition_id),
INDEX idx_form_key (form_key),
INDEX idx_category_id (category_id),
@ -703,7 +703,7 @@ CREATE TABLE deploy_application_category
icon VARCHAR(50) NULL COMMENT '图标',
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用0禁用1启用',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
UNIQUE INDEX uk_code (code)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
@ -745,46 +745,46 @@ CREATE TABLE deploy_application
CREATE TABLE deploy_environment
(
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
-- 业务字段
tenant_code VARCHAR(50) DEFAULT NULL COMMENT '租户编码',
env_code VARCHAR(50) NOT NULL COMMENT '环境编码',
env_name VARCHAR(100) NOT NULL COMMENT '环境名称',
env_desc VARCHAR(255) NULL COMMENT '环境描述',
-- 业务字段
tenant_code VARCHAR(50) DEFAULT NULL COMMENT '租户编码',
env_code VARCHAR(50) NOT NULL COMMENT '环境编码',
env_name VARCHAR(100) NOT NULL COMMENT '环境名称',
env_desc VARCHAR(255) NULL COMMENT '环境描述',
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用0禁用1启用',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
-- 基础字段
create_by VARCHAR(100) NULL COMMENT '创建人',
-- 基础字段
create_by VARCHAR(100) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
-- 索引
UNIQUE INDEX uk_env_code (env_code) COMMENT '环境编码唯一'
-- 索引
UNIQUE INDEX uk_env_code (env_code) COMMENT '环境编码唯一'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='环境表';
-- 团队表
CREATE TABLE deploy_team
(
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
team_code VARCHAR(50) NOT NULL COMMENT '团队编码',
team_name VARCHAR(100) NOT NULL COMMENT '团队名称',
description VARCHAR(500) NULL COMMENT '团队描述',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
team_code VARCHAR(50) NOT NULL COMMENT '团队编码',
team_name VARCHAR(100) NOT NULL COMMENT '团队名称',
description VARCHAR(500) NULL COMMENT '团队描述',
owner_id BIGINT NULL COMMENT '团队负责人用户ID',
owner_name VARCHAR(50) NULL COMMENT '团队负责人姓名(冗余)',
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
UNIQUE INDEX uk_team_code (team_code),
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
UNIQUE INDEX uk_team_code (team_code),
INDEX idx_owner (owner_id),
CONSTRAINT fk_team_owner FOREIGN KEY (owner_id) REFERENCES sys_user (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='团队表';
@ -792,21 +792,21 @@ CREATE TABLE deploy_team
-- 团队成员表
CREATE TABLE deploy_team_member
(
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
team_id BIGINT NOT NULL COMMENT '团队ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
user_name VARCHAR(50) NULL COMMENT '用户名(冗余)',
role_in_team VARCHAR(50) NULL COMMENT '团队角色(如:开发、测试、运维、负责人)',
join_time DATETIME(6) NULL COMMENT '加入时间',
UNIQUE INDEX uk_team_user (team_id, user_id),
UNIQUE INDEX uk_team_user (team_id, user_id),
INDEX idx_user (user_id),
CONSTRAINT fk_team_member_team FOREIGN KEY (team_id) REFERENCES deploy_team (id),
CONSTRAINT fk_team_member_user FOREIGN KEY (user_id) REFERENCES sys_user (id)
@ -815,14 +815,14 @@ CREATE TABLE deploy_team_member
-- 团队应用关联表
CREATE TABLE deploy_team_application
(
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
team_id BIGINT NOT NULL COMMENT '团队ID',
application_id BIGINT NOT NULL COMMENT '应用ID',
environment_id BIGINT NOT NULL COMMENT '环境ID',
@ -830,8 +830,8 @@ CREATE TABLE deploy_team_application
deploy_system_id BIGINT NULL COMMENT '部署系统ID关联sys_external_systemtype=JENKINS',
deploy_job VARCHAR(100) NULL COMMENT '部署任务ID关联deploy_jenkins_job',
workflow_definition_id BIGINT NULL COMMENT '工作流定义ID关联workflow_definition',
UNIQUE INDEX uk_team_app_env (team_id, application_id, environment_id),
UNIQUE INDEX uk_team_app_env (team_id, application_id, environment_id),
INDEX idx_team (team_id),
INDEX idx_application (application_id),
INDEX idx_environment (environment_id),
@ -852,17 +852,17 @@ CREATE TABLE deploy_team_config
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
team_id BIGINT NOT NULL COMMENT '团队ID',
-- 环境权限配置
-- 环境权限配置
allowed_environment_ids JSON NULL COMMENT '团队可访问的环境ID列表[1, 2, 3]',
-- 审批配置与allowed_environment_ids位置对应
-- 审批配置与allowed_environment_ids位置对应
environment_approval_required JSON NULL COMMENT '各环境是否需要审批boolean数组[false, false, true]',
approver_user_ids JSON NULL COMMENT '各环境的审批人列表数组无审批人用null[null, null, [1, 4]]',
UNIQUE INDEX uk_team (team_id),
UNIQUE INDEX uk_team (team_id),
INDEX idx_deleted (deleted),
CONSTRAINT fk_team_config_team FOREIGN KEY (team_id) REFERENCES deploy_team (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='团队配置表';
@ -874,20 +874,20 @@ CREATE TABLE deploy_team_config
-- 通知渠道配置表
CREATE TABLE sys_notification_channel
(
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除0未删除1已删除',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
name VARCHAR(100) NOT NULL COMMENT '渠道名称(如:研发部企业微信群)',
name VARCHAR(100) NOT NULL COMMENT '渠道名称(如:研发部企业微信群)',
channel_type VARCHAR(50) NOT NULL COMMENT '渠道类型WEWORK, FEISHU, DINGTALK, SMS, EMAIL, SLACK',
config JSON NOT NULL COMMENT '渠道配置JSON格式不同渠道存储不同字段',
status VARCHAR(20) NOT NULL DEFAULT 'ENABLED' COMMENT '状态ENABLED-启用, DISABLED-禁用)',
description VARCHAR(500) NULL COMMENT '描述说明',
description VARCHAR(500) NULL COMMENT '描述说明',
INDEX idx_channel_type (channel_type),
INDEX idx_status (status),
INDEX idx_deleted (deleted)
@ -900,23 +900,23 @@ CREATE TABLE sys_notification_channel
-- 定时任务分类表
CREATE TABLE schedule_job_category
(
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(100) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_by VARCHAR(100) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
code VARCHAR(50) NOT NULL COMMENT '分类编码',
name VARCHAR(100) NOT NULL COMMENT '分类名称',
description VARCHAR(500) NULL COMMENT '描述',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
code VARCHAR(50) NOT NULL COMMENT '分类编码',
name VARCHAR(100) NOT NULL COMMENT '分类名称',
description VARCHAR(500) NULL COMMENT '描述',
icon VARCHAR(50) NULL COMMENT '图标',
color VARCHAR(20) NULL COMMENT '颜色',
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
UNIQUE INDEX uk_code (code, deleted),
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
UNIQUE INDEX uk_code (code, deleted),
INDEX idx_enabled (enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='定时任务分类表';
@ -930,35 +930,35 @@ CREATE TABLE schedule_job
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
job_name VARCHAR(100) NOT NULL COMMENT '任务名称',
job_description VARCHAR(500) NULL COMMENT '任务描述',
category_id BIGINT NOT NULL COMMENT '任务分类ID',
-- 执行配置
-- 执行配置
bean_name VARCHAR(100) NOT NULL COMMENT 'Spring Bean名称',
method_name VARCHAR(100) NOT NULL COMMENT '方法名称',
form_definition_id BIGINT NULL COMMENT '参数表单ID',
method_params TEXT NULL COMMENT '方法参数JSON',
-- 调度配置
-- 调度配置
cron_expression VARCHAR(100) NOT NULL COMMENT 'Cron表达式',
status VARCHAR(20) NOT NULL DEFAULT 'ENABLED' COMMENT '任务状态ENABLED-启用、DISABLED-禁用、PAUSED-暂停',
concurrent BIT NOT NULL DEFAULT 0 COMMENT '是否允许并发执行',
-- 统计信息
-- 统计信息
last_execute_time DATETIME(6) NULL COMMENT '上次执行时间',
next_execute_time DATETIME(6) NULL COMMENT '下次执行时间',
execute_count INT NOT NULL DEFAULT 0 COMMENT '执行次数',
success_count INT NOT NULL DEFAULT 0 COMMENT '成功次数',
fail_count INT NOT NULL DEFAULT 0 COMMENT '失败次数',
-- 高级配置
-- 高级配置
timeout_seconds INT NULL COMMENT '超时时间(秒)',
retry_count INT NOT NULL DEFAULT 0 COMMENT '失败重试次数',
alert_email VARCHAR(500) NULL COMMENT '告警邮箱(多个用逗号分隔)',
UNIQUE INDEX uk_job_name (job_name, deleted),
UNIQUE INDEX uk_job_name (job_name, deleted),
INDEX idx_category (category_id),
INDEX idx_status (status),
INDEX idx_next_execute_time (next_execute_time),
@ -976,29 +976,29 @@ CREATE TABLE schedule_job_log
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
job_id BIGINT NOT NULL COMMENT '任务ID',
job_name VARCHAR(100) NOT NULL COMMENT '任务名称',
-- 执行信息
-- 执行信息
bean_name VARCHAR(100) NOT NULL COMMENT '执行器Bean名称',
method_name VARCHAR(100) NOT NULL COMMENT '执行方法名称',
method_params TEXT NULL COMMENT '方法参数',
-- 时间统计
-- 时间统计
execute_time DATETIME(6) NOT NULL COMMENT '开始执行时间',
finish_time DATETIME(6) NULL COMMENT '完成时间',
duration BIGINT NULL COMMENT '执行耗时(毫秒)',
-- 状态信息
-- 状态信息
status VARCHAR(20) NOT NULL COMMENT '执行状态SUCCESS-成功、FAIL-失败、TIMEOUT-超时',
result_message TEXT NULL COMMENT '执行结果消息',
exception_info TEXT NULL COMMENT '异常堆栈信息',
-- 服务器信息
-- 服务器信息
server_ip VARCHAR(50) NULL COMMENT '执行服务器IP',
server_host VARCHAR(100) NULL COMMENT '执行服务器主机名',
INDEX idx_job_id (job_id),
INDEX idx_execute_time (execute_time),
INDEX idx_status (status),
@ -1019,15 +1019,15 @@ CREATE TABLE deploy_server_category
description VARCHAR(500) NULL COMMENT '分类描述',
sort INT DEFAULT 0 COMMENT '排序',
enabled BOOLEAN DEFAULT TRUE COMMENT '是否启用',
-- 审计字段
-- 审计字段
create_by VARCHAR(50) NULL COMMENT '创建人',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by VARCHAR(50) NULL COMMENT '更新人',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
version INT DEFAULT 1 COMMENT '版本号',
deleted BOOLEAN DEFAULT FALSE COMMENT '是否删除',
INDEX idx_code (code),
INDEX idx_enabled (enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='服务器分类表';
@ -1036,34 +1036,34 @@ CREATE TABLE deploy_server_category
CREATE TABLE deploy_server
(
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
server_name VARCHAR(100) NOT NULL COMMENT '服务器名称',
host_ip VARCHAR(50) NOT NULL UNIQUE COMMENT 'IP地址',
server_name VARCHAR(100) NOT NULL COMMENT '服务器名称',
host_ip VARCHAR(50) NOT NULL UNIQUE COMMENT 'IP地址',
ssh_port INT DEFAULT 22 COMMENT 'SSH端口',
ssh_user VARCHAR(50) NULL COMMENT 'SSH用户名',
auth_type VARCHAR(20) DEFAULT 'PASSWORD' COMMENT '认证方式PASSWORD/KEY',
ssh_password VARCHAR(500) NULL COMMENT 'SSH密码加密存储',
ssh_password VARCHAR(500) NULL COMMENT 'SSH密码加密存储',
ssh_private_key TEXT NULL COMMENT 'SSH私钥加密存储',
ssh_passphrase VARCHAR(500) NULL COMMENT '私钥密码(加密存储)',
ssh_passphrase VARCHAR(500) NULL COMMENT '私钥密码(加密存储)',
category_id BIGINT NULL COMMENT '服务器分类ID',
os_type VARCHAR(20) NULL COMMENT '操作系统类型LINUX/WINDOWS/MACOS/UNIX/OTHER',
os_version VARCHAR(100) NULL COMMENT '操作系统版本CentOS 7.9',
hostname VARCHAR(100) NULL COMMENT '主机名',
os_version VARCHAR(100) NULL COMMENT '操作系统版本CentOS 7.9',
hostname VARCHAR(100) NULL COMMENT '主机名',
status VARCHAR(20) DEFAULT 'OFFLINE' COMMENT '连接状态ONLINE/OFFLINE',
description VARCHAR(500) NULL COMMENT '服务器描述',
description VARCHAR(500) NULL COMMENT '服务器描述',
cpu_cores INT NULL COMMENT 'CPU核心数',
memory_size INT NULL COMMENT '内存大小(GB)',
disk_size INT NULL COMMENT '磁盘大小(GB)',
tags JSON NULL COMMENT '标签JSON格式',
last_connect_time DATETIME NULL COMMENT '最后连接时间',
-- 审计字段
-- 审计字段
create_by VARCHAR(50) NULL COMMENT '创建人',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by VARCHAR(50) NULL COMMENT '更新人',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
version INT DEFAULT 1 COMMENT '版本号',
deleted BOOLEAN DEFAULT FALSE COMMENT '是否删除',
INDEX idx_host_ip (host_ip),
INDEX idx_category_id (category_id),
INDEX idx_status (status),