反序列化问题。

This commit is contained in:
dengqichen 2024-12-23 13:50:51 +08:00
parent 0e430c3036
commit 66a59ad039
31 changed files with 799 additions and 101 deletions

View File

@ -0,0 +1,23 @@
package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.deploy.dto.ApplicationDTO;
import com.qqchen.deploy.backend.deploy.entity.Application;
import com.qqchen.deploy.backend.deploy.query.ApplicationQuery;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "应用管理", description = "应用管理相关接口")
@RestController
@RequestMapping("/api/v1/application")
public class ApplicationApiController extends BaseController<Application, ApplicationDTO, Long, ApplicationQuery> {
@Override
protected void exportData(HttpServletResponse response, List<ApplicationDTO> data) {
// TODO: 实现导出逻辑
}
}

View File

@ -0,0 +1,23 @@
package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.deploy.dto.ProjectDTO;
import com.qqchen.deploy.backend.deploy.entity.Project;
import com.qqchen.deploy.backend.deploy.query.ProjectQuery;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "项目管理", description = "项目管理相关接口")
@RestController
@RequestMapping("/api/v1/project")
public class ProjectApiController extends BaseController<Project, ProjectDTO, Long, ProjectQuery> {
@Override
protected void exportData(HttpServletResponse response, List<ProjectDTO> data) {
// TODO: 实现导出逻辑
}
}

View File

@ -0,0 +1,10 @@
package com.qqchen.deploy.backend.deploy.converter;
import com.qqchen.deploy.backend.deploy.dto.ApplicationDTO;
import com.qqchen.deploy.backend.deploy.entity.Application;
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import org.mapstruct.Mapper;
@Mapper(config = BaseConverter.class)
public interface ApplicationConverter extends BaseConverter<Application, ApplicationDTO> {
}

View File

@ -0,0 +1,10 @@
package com.qqchen.deploy.backend.deploy.converter;
import com.qqchen.deploy.backend.deploy.dto.ProjectDTO;
import com.qqchen.deploy.backend.deploy.entity.Project;
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import org.mapstruct.Mapper;
@Mapper(config = BaseConverter.class)
public interface ProjectConverter extends BaseConverter<Project, ProjectDTO> {
}

View File

@ -0,0 +1,41 @@
package com.qqchen.deploy.backend.deploy.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;
@Data
@EqualsAndHashCode(callSuper = true)
public class ApplicationDTO extends BaseDTO {
@NotNull(message = "项目ID不能为空")
private Long projectId;
@NotBlank(message = "应用编码不能为空")
private String appCode;
@NotBlank(message = "应用名称不能为空")
private String appName;
private String appDesc;
@NotBlank(message = "应用状态不能为空")
private String appStatus;
private String repoUrl;
private String repoBranch;
private String repoType;
private String buildType;
private String devLanguage;
private String devFramework;
@NotNull(message = "排序号不能为空")
private Integer sort;
}

View File

@ -0,0 +1,29 @@
package com.qqchen.deploy.backend.deploy.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;
@Data
@EqualsAndHashCode(callSuper = true)
public class ProjectDTO extends BaseDTO {
@NotNull(message = "租户ID不能为空")
private Long tenantId;
@NotBlank(message = "项目编码不能为空")
private String projectCode;
@NotBlank(message = "项目名称不能为空")
private String projectName;
private String projectDesc;
@NotBlank(message = "项目状态不能为空")
private String projectStatus;
@NotNull(message = "排序号不能为空")
private Integer sort;
}

View File

@ -0,0 +1,50 @@
package com.qqchen.deploy.backend.deploy.entity;
import com.qqchen.deploy.backend.framework.domain.Entity;
import jakarta.persistence.Column;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@jakarta.persistence.Entity
@Table(name = "deploy_application")
public class Application extends Entity<Long> {
@Column(name = "project_id", nullable = false)
private Long projectId;
@Column(name = "app_code", nullable = false)
private String appCode;
@Column(name = "app_name", nullable = false)
private String appName;
@Column(name = "app_desc")
private String appDesc;
@Column(name = "app_status", nullable = false)
private String appStatus;
@Column(name = "repo_url")
private String repoUrl;
@Column(name = "repo_branch")
private String repoBranch;
@Column(name = "repo_type")
private String repoType;
@Column(name = "build_type")
private String buildType;
@Column(name = "dev_language")
private String devLanguage;
@Column(name = "dev_framework")
private String devFramework;
@Column(name = "sort", nullable = false)
private Integer sort;
}

View File

@ -0,0 +1,53 @@
package com.qqchen.deploy.backend.deploy.entity;
import com.qqchen.deploy.backend.framework.domain.Entity;
import jakarta.persistence.Column;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 项目组实体
*/
@Data
@EqualsAndHashCode(callSuper = true)
@jakarta.persistence.Entity
@Table(name = "deploy_project")
public class Project extends Entity<Long> {
/**
* 租户ID
*/
@Column(name = "tenant_id", nullable = false)
private Long tenantId;
/**
* 项目编码
*/
@Column(name = "project_code", nullable = false)
private String projectCode;
/**
* 项目名称
*/
@Column(name = "project_name", nullable = false)
private String projectName;
/**
* 项目描述
*/
@Column(name = "project_desc")
private String projectDesc;
/**
* 项目状态
*/
@Column(name = "project_status", nullable = false)
private String projectStatus;
/**
* 排序号
*/
@Column(name = "sort", nullable = false)
private Integer sort;
}

View File

@ -0,0 +1,33 @@
package com.qqchen.deploy.backend.deploy.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 lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class ApplicationQuery extends BaseQuery {
@QueryField(field = "appCode", type = QueryType.LIKE)
private String appCode;
@QueryField(field = "appName", type = QueryType.LIKE)
private String appName;
@QueryField(field = "appStatus")
private String appStatus;
@QueryField(field = "projectId")
private Long projectId;
@QueryField(field = "repoType")
private String repoType;
@QueryField(field = "buildType")
private String buildType;
@QueryField(field = "devLanguage")
private String devLanguage;
}

View File

@ -0,0 +1,24 @@
package com.qqchen.deploy.backend.deploy.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 lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class ProjectQuery extends BaseQuery {
@QueryField(field = "projectCode", type = QueryType.LIKE)
private String projectCode;
@QueryField(field = "projectName", type = QueryType.LIKE)
private String projectName;
@QueryField(field = "projectStatus")
private String projectStatus;
@QueryField(field = "tenantId")
private Long tenantId;
}

View File

@ -0,0 +1,10 @@
package com.qqchen.deploy.backend.deploy.repository;
import com.qqchen.deploy.backend.deploy.entity.Application;
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface IApplicationRepository extends IBaseRepository<Application, Long> {
boolean existsByAppCodeAndProjectIdAndDeletedFalse(String appCode, Long projectId);
}

View File

@ -0,0 +1,10 @@
package com.qqchen.deploy.backend.deploy.repository;
import com.qqchen.deploy.backend.deploy.entity.Project;
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface IProjectRepository extends IBaseRepository<Project, Long> {
boolean existsByProjectCodeAndTenantIdAndDeletedFalse(String projectCode, Long tenantId);
}

View File

@ -0,0 +1,8 @@
package com.qqchen.deploy.backend.deploy.service;
import com.qqchen.deploy.backend.deploy.dto.ApplicationDTO;
import com.qqchen.deploy.backend.deploy.entity.Application;
import com.qqchen.deploy.backend.framework.service.IBaseService;
public interface IApplicationService extends IBaseService<Application, ApplicationDTO, Long> {
}

View File

@ -0,0 +1,8 @@
package com.qqchen.deploy.backend.deploy.service;
import com.qqchen.deploy.backend.deploy.dto.ProjectDTO;
import com.qqchen.deploy.backend.deploy.entity.Project;
import com.qqchen.deploy.backend.framework.service.IBaseService;
public interface IProjectService extends IBaseService<Project, ProjectDTO, Long> {
}

View File

@ -0,0 +1,12 @@
package com.qqchen.deploy.backend.deploy.service.impl;
import com.qqchen.deploy.backend.deploy.dto.ApplicationDTO;
import com.qqchen.deploy.backend.deploy.entity.Application;
import com.qqchen.deploy.backend.deploy.service.IApplicationService;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class ApplicationServiceImpl extends BaseServiceImpl<Application, ApplicationDTO, Long> implements IApplicationService {
}

View File

@ -0,0 +1,12 @@
package com.qqchen.deploy.backend.deploy.service.impl;
import com.qqchen.deploy.backend.deploy.dto.ProjectDTO;
import com.qqchen.deploy.backend.deploy.entity.Project;
import com.qqchen.deploy.backend.deploy.service.IProjectService;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class ProjectServiceImpl extends BaseServiceImpl<Project, ProjectDTO, Long> implements IProjectService {
}

View File

@ -6,7 +6,34 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* Schema属性注解 * Schema属性注解用于定义工作流节点表单字段的属性
*
* <p>使用示例
* <pre>
* {@code
* @SchemaProperty(
* title = "项目",
* description = "选择项目",
* required = true,
* dataSource = @SchemaPropertyDataSource(
* type = "api",
* url = "/api/v1/projects",
* valueField = "id",
* labelField = "name"
* )
* )
* private String projectId;
* }
* </pre>
*
* <p>支持的功能
* <ul>
* <li>基本属性标题描述是否必填等</li>
* <li>数据源配置支持动态数据源如API调用</li>
* <li>数值范围支持最大值和最小值限制</li>
* <li>枚举值支持固定选项及其显示名称</li>
* <li>字段显示控制支持隐藏字段</li>
* </ul>
*/ */
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ -15,42 +42,53 @@ public @interface SchemaProperty {
* 字段标题 * 字段标题
*/ */
String title() default ""; String title() default "";
/** /**
* 字段描述 * 字段描述
*/ */
String description() default ""; String description() default "";
/** /**
* 是否必填 * 是否必填
*/ */
boolean required() default false; boolean required() default false;
/** /**
* 字段格式 * 字段格式
*/ */
String format() default ""; String format() default "";
/**
* 控制字段是否在表单中显示
*/
boolean hidden() default false;
/**
* 数据源配置用于定义字段的数据来源
* @see SchemaPropertyDataSource
*/
SchemaPropertyDataSource dataSource() default @SchemaPropertyDataSource(type = "");
/** /**
* 默认值 * 默认值
*/ */
String defaultValue() default ""; String defaultValue() default "";
/** /**
* 最小值用于数值类型 * 最小值用于数值类型
*/ */
int minimum() default Integer.MIN_VALUE; int minimum() default Integer.MIN_VALUE;
/** /**
* 最大值用于数值类型 * 最大值用于数值类型
*/ */
int maximum() default Integer.MAX_VALUE; int maximum() default Integer.MAX_VALUE;
/** /**
* 枚举值用于字符串类型 * 枚举值用于字符串类型
*/ */
String[] enumValues() default {}; String[] enumValues() default {};
/** /**
* 枚举值显示名称 * 枚举值显示名称
*/ */

View File

@ -0,0 +1,74 @@
package com.qqchen.deploy.backend.workflow.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Schema属性的数据源配置注解用于定义表单字段的数据来源
*
* <p>主要用途
* <ul>
* <li>定义动态数据源如API接口</li>
* <li>配置数据字段映射关系</li>
* <li>设置字段间的依赖关系</li>
* <li>配置请求参数</li>
* </ul>
*
* <p>使用示例
* <pre>
* {@code
* @SchemaProperty(
* title = "Jenkins视图",
* description = "Jenkins视图名称",
* required = true,
* dataSource = @SchemaPropertyDataSource(
* type = "api",
* url = "/api/v1/jenkins/views",
* valueField = "name",
* labelField = "name",
* dependsOn = {"projectId"},
* params = {
* @SchemaPropertyDataSourceParam(name = "projectId", value = "${projectId}")
* }
* )
* )
* private String view;
* }
* </pre>
*/
@Target({})
@Retention(RetentionPolicy.RUNTIME)
public @interface SchemaPropertyDataSource {
/**
* 数据源类型 "api""enum"
*/
String type() default "";
/**
* 数据源URL当type为"api"时使用
*/
String url() default "";
/**
* 值字段名称用于指定选项值的来源字段
*/
String valueField() default "value";
/**
* 标签字段名称用于指定选项显示文本的来源字段
*/
String labelField() default "label";
/**
* 依赖字段列表用于指定当前字段依赖的其他字段
* 当依赖字段值变化时需要重新获取当前字段的选项数据
*/
String[] dependsOn() default {};
/**
* 请求参数配置用于API调用时传递参数
* @see SchemaPropertyDataSourceParam
*/
SchemaPropertyDataSourceParam[] params() default {};
}

View File

@ -0,0 +1,45 @@
package com.qqchen.deploy.backend.workflow.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Schema属性数据源的参数配置注解用于定义API请求参数
*
* <p>主要用途
* <ul>
* <li>配置API请求参数的名称和值</li>
* <li>支持动态参数值使用${fieldName}引用其他字段的值</li>
* </ul>
*
* <p>使用示例
* <pre>
* {@code
* @SchemaProperty(
* dataSource = @SchemaPropertyDataSource(
* type = "api",
* url = "/api/v1/jenkins/jobs",
* params = {
* @SchemaPropertyDataSourceParam(name = "projectId", value = "${projectId}"),
* @SchemaPropertyDataSourceParam(name = "view", value = "${view}")
* }
* )
* )
* private String job;
* }
* </pre>
*/
@Target({})
@Retention(RetentionPolicy.RUNTIME)
public @interface SchemaPropertyDataSourceParam {
/**
* 参数名称
*/
String name();
/**
* 参数值支持使用${fieldName}引用其他字段的值
*/
String value();
}

View File

@ -24,7 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/ */
@Slf4j @Slf4j
@Component @Component
public class JenkinsNodeDelegate extends BaseNodeDelegate<ScriptNodePanelVariables, ScriptNodeLocalVariables> { public class JenkinsJobTriggerDelegate extends BaseNodeDelegate<ScriptNodePanelVariables, ScriptNodeLocalVariables> {
@Resource @Resource
private ApplicationEventPublisher eventPublisher; private ApplicationEventPublisher eventPublisher;

View File

@ -3,7 +3,6 @@ package com.qqchen.deploy.backend.workflow.dto;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.qqchen.deploy.backend.framework.dto.BaseDTO; import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import com.qqchen.deploy.backend.workflow.dto.definition.node.uiVariables.NodeUiVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.uiVariables.NodeUiVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowNodeGraph;
import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnums; import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnums;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums; import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -9,11 +9,6 @@ import lombok.Data;
@Data @Data
public class BaseNodeFormVariables { public class BaseNodeFormVariables {
@SchemaProperty(
title = "委派者",
description = "委派者",
required = true
)
private String delegate;
} }

View File

@ -0,0 +1,61 @@
package com.qqchen.deploy.backend.workflow.dto.definition.node.fromVariables;
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
import com.qqchen.deploy.backend.workflow.annotation.SchemaPropertyDataSource;
import com.qqchen.deploy.backend.workflow.annotation.SchemaPropertyDataSourceParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class JenkinsJobTriggerNodeFormVariables extends BaseNodeFormVariables {
@SchemaProperty(
title = "项目",
description = "选择项目",
required = true,
dataSource = @SchemaPropertyDataSource(
type = "api",
url = "/api/v1/projects",
valueField = "id",
labelField = "name"
)
)
private String projectId;
@SchemaProperty(
title = "Jenkins视图",
description = "Jenkins视图名称",
required = true,
dataSource = @SchemaPropertyDataSource(
type = "api",
url = "/api/v1/jenkins/views",
valueField = "name",
labelField = "name",
dependsOn = {"projectId"},
params = {
@SchemaPropertyDataSourceParam(name = "projectId", value = "${projectId}")
}
)
)
private String view;
@SchemaProperty(
title = "Jenkins任务",
description = "Jenkins任务名称",
required = true,
dataSource = @SchemaPropertyDataSource(
type = "api",
url = "/api/v1/jenkins/jobs",
valueField = "name",
labelField = "name",
dependsOn = {"projectId", "view"},
params = {
@SchemaPropertyDataSourceParam(name = "projectId", value = "${projectId}"),
@SchemaPropertyDataSourceParam(name = "view", value = "${view}")
}
)
)
private String job;
}

View File

@ -6,12 +6,12 @@ import lombok.EqualsAndHashCode;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class JenkinsNodeLocalVariables extends BaseNodeLocalVariables { public class JenkinsJobTriggerNodeLocalVariables extends BaseNodeLocalVariables {
@SchemaProperty( @SchemaProperty(
title = "委派者", title = "委派者",
description = "委派者", description = "委派者",
defaultValue = "${jenkinsNodeDelegate}", defaultValue = "${jenkinsJobTriggerDelegate}",
required = true required = true
) )
private String delegate; private String delegate;

View File

@ -0,0 +1,35 @@
package com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables;
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 脚本执行器配置
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class JenkinsJobTriggerNodePanelVariables extends BaseNodePanelVariables {
// @SchemaProperty(
// title = "环境",
// description = "环境",
// required = true
// )
// private String environment;
//
// /**
// * 脚本语言
// */
// @SchemaProperty(
// title = "任务名",
// description = "任务名",
// required = true,
// enumNames = {"Shell脚本 (已支持)", "Python脚本 (开发中)", "JavaScript脚本 (开发中)", "Groovy脚本 (开发中)"},
// defaultValue = "shell"
// )
// private String job;
}

View File

@ -1,66 +0,0 @@
package com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables;
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 脚本执行器配置
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class JenkinsNodePanelVariables extends BaseNodePanelVariables {
@SchemaProperty(
title = "脚本代码",
description = "脚本代码",
required = true
)
private String script;
/**
* 脚本语言
*/
@SchemaProperty(
title = "脚本语言",
description = "脚本语言类型",
required = true,
enumValues = {"shell", "python", "javascript", "groovy"},
enumNames = {"Shell脚本 (已支持)", "Python脚本 (开发中)", "JavaScript脚本 (开发中)", "Groovy脚本 (开发中)"},
defaultValue = "shell"
)
private String language;
/**
* 解释器路径
*/
@SchemaProperty(
title = "解释器路径",
description = "脚本解释器的路径,例如:/bin/bash, /usr/bin/python3",
required = true
)
private String interpreter;
/**
* 成功退出码
*/
@SchemaProperty(
title = "成功标识",
description = "脚本执行成功时的标识",
required = true
)
private Integer successExitCode;
/**
* 支持的脚本语言列表
*/
@SchemaProperty(
title = "支持的脚本语言",
enumValues = {"shell", "python", "javascript", "groovy"}
)
private List<String> supportedLanguages;
}

View File

@ -9,16 +9,16 @@ public class Size {
@SchemaProperty( @SchemaProperty(
title = "宽度", title = "宽度",
description = "节点的宽度", description = "节点的宽度",
required = true, required = true
defaultValue = "120" // defaultValue = "120"
) )
private Integer width; private Integer width;
@SchemaProperty( @SchemaProperty(
title = "高度", title = "高度",
description = "节点的高度", description = "节点的高度",
required = true, required = true
defaultValue = "60" // defaultValue = "60"
) )
private Integer height; private Integer height;
} }

View File

@ -1,9 +1,12 @@
package com.qqchen.deploy.backend.workflow.enums; package com.qqchen.deploy.backend.workflow.enums;
import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.annotation.JsonValue;
import com.qqchen.deploy.backend.workflow.dto.definition.node.fromVariables.JenkinsJobTriggerNodeFormVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.fromVariables.ScriptNodeFormVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.fromVariables.ScriptNodeFormVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.localVariables.JenkinsJobTriggerNodeLocalVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.localVariables.ScriptNodeLocalVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.localVariables.ScriptNodeLocalVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.EndNodePanelVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.EndNodePanelVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.JenkinsJobTriggerNodePanelVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.ScriptNodePanelVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.ScriptNodePanelVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.StartNodePanelVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.StartNodePanelVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.uiVariables.NodeUiVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.uiVariables.NodeUiVariables;
@ -66,8 +69,8 @@ public enum NodeTypeEnums {
.setStyle("#fff1f0", "#ff4d4f", "stop") .setStyle("#fff1f0", "#ff4d4f", "stop")
.configPorts(Arrays.asList("in")) .configPorts(Arrays.asList("in"))
), ),
SCRIPT_TASK( SCRIPT_NODE(
"SCRIPT_TASK", "SCRIPT_NODE",
"脚本任务", "脚本任务",
ScriptNodeLocalVariables.class, ScriptNodeLocalVariables.class,
ScriptNodePanelVariables.class, ScriptNodePanelVariables.class,
@ -81,6 +84,18 @@ public enum NodeTypeEnums {
.setSize(120, 60) .setSize(120, 60)
.setStyle("#ffffff", "#1890ff", "code") .setStyle("#ffffff", "#1890ff", "code")
.configPorts(Arrays.asList("in", "out")) .configPorts(Arrays.asList("in", "out"))
),
JENKINS_NODE(
"JENKINS_JOB_TRIGGER",
"JENKINS任务触发",
JenkinsJobTriggerNodeLocalVariables.class,
JenkinsJobTriggerNodePanelVariables.class,
JenkinsJobTriggerNodeFormVariables.class,
NodeUiVariables.class,
BpmnNodeTypeEnums.SERVICE_TASK,
NodeCategoryEnums.TASK,
"JENKINS任务触发",
null
); );
// //
// /** // /**

View File

@ -5,6 +5,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty; import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
import com.qqchen.deploy.backend.workflow.annotation.SchemaPropertyDataSource;
import com.qqchen.deploy.backend.workflow.annotation.SchemaPropertyDataSourceParam;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.BaseNodePanelVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.BaseNodePanelVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.EndNodePanelVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.EndNodePanelVariables;
import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.ScriptNodePanelVariables; import com.qqchen.deploy.backend.workflow.dto.definition.node.panelVariables.ScriptNodePanelVariables;
@ -34,7 +36,7 @@ public class SchemaGenerator {
return StartNodePanelVariables.class; return StartNodePanelVariables.class;
case END_EVENT: case END_EVENT:
return EndNodePanelVariables.class; return EndNodePanelVariables.class;
case SCRIPT_TASK: case SCRIPT_NODE:
return ScriptNodePanelVariables.class; return ScriptNodePanelVariables.class;
// 其他节点类型的配置类 // 其他节点类型的配置类
// case USER_TASK: // case USER_TASK:
@ -60,7 +62,7 @@ public class SchemaGenerator {
for (NodeTypeEnums nodeType : NodeTypeEnums.values()) { for (NodeTypeEnums nodeType : NodeTypeEnums.values()) {
// 获取节点类型对应的配置类 // 获取节点类型对应的配置类
Class<?> configClass = getConfigClassForNodeType(nodeType); Class<?> configClass = getConfigClassForNodeType(nodeType);
// 生成该节点类型的schema // 生成该节点的schema
ObjectNode nodeSchema = generateNodeSchema(nodeType, configClass); ObjectNode nodeSchema = generateNodeSchema(nodeType, configClass);
schemas.add(nodeSchema); schemas.add(nodeSchema);
} }
@ -74,7 +76,7 @@ public class SchemaGenerator {
private static ObjectNode generateNodeSchema(NodeTypeEnums nodeType, Class<?> configClass) { private static ObjectNode generateNodeSchema(NodeTypeEnums nodeType, Class<?> configClass) {
ObjectNode node = mapper.createObjectNode(); ObjectNode node = mapper.createObjectNode();
// 设置基本信 // 设置基本信<EFBFBD><EFBFBD>
node.put("code", nodeType.getCode()); node.put("code", nodeType.getCode());
node.put("name", nodeType.getName()); node.put("name", nodeType.getName());
// node.put("description", nodeType.getShortDesc()); // node.put("description", nodeType.getShortDesc());
@ -178,7 +180,7 @@ public class SchemaGenerator {
} }
/** /**
* 处理基础字codenamedescription * 处理基础字<EFBFBD><EFBFBD><EFBFBD>codenamedescription
*/ */
private static void processBaseFields(ObjectNode properties, List<String> required, Class<?> configClass) { private static void processBaseFields(ObjectNode properties, List<String> required, Class<?> configClass) {
String[] baseFields = {"code", "name", "description"}; String[] baseFields = {"code", "name", "description"};
@ -238,6 +240,41 @@ public class SchemaGenerator {
fieldSchema.put("description", annotation.description()); fieldSchema.put("description", annotation.description());
} }
// 处理hidden属性
if (annotation.hidden()) {
fieldSchema.put("hidden", true);
}
// 处理数据源属性
SchemaPropertyDataSource dataSource = annotation.dataSource();
if (!dataSource.type().isEmpty()) {
ObjectNode dataSourceNode = fieldSchema.putObject("x-data-source");
dataSourceNode.put("type", dataSource.type());
if (!dataSource.url().isEmpty()) {
dataSourceNode.put("url", dataSource.url());
}
dataSourceNode.put("valueField", dataSource.valueField());
dataSourceNode.put("labelField", dataSource.labelField());
// 处理依赖字段
if (dataSource.dependsOn().length > 0) {
ArrayNode dependsOn = dataSourceNode.putArray("dependsOn");
for (String dep : dataSource.dependsOn()) {
dependsOn.add(dep);
}
}
// 处理参数
if (dataSource.params().length > 0) {
ObjectNode params = dataSourceNode.putObject("params");
for (SchemaPropertyDataSourceParam param : dataSource.params()) {
params.put(param.name(), param.value());
}
}
}
// 处理format // 处理format
if (!annotation.format().isEmpty()) { if (!annotation.format().isEmpty()) {
fieldSchema.put("format", annotation.format()); fieldSchema.put("format", annotation.format());
@ -274,7 +311,7 @@ public class SchemaGenerator {
} }
} }
// 处理数类型 // 处理数类型
if (jsonType.equals("array")) { if (jsonType.equals("array")) {
ObjectNode items = fieldSchema.putObject("items"); ObjectNode items = fieldSchema.putObject("items");
if (field.getType().isArray()) { if (field.getType().isArray()) {

View File

@ -535,3 +535,71 @@ CREATE TABLE workflow_log
CONSTRAINT FK_workflow_log_node_instance FOREIGN KEY (node_instance_id) REFERENCES workflow_node_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='工作流日志表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流日志表';
-- --------------------------------------------------------------------------------------
-- 项目管理相关表
-- --------------------------------------------------------------------------------------
-- 项目组表
CREATE TABLE deploy_project
(
-- 基础字段
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_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除0-未删除1-已删除',
-- 业务字段
tenant_id BIGINT NOT NULL COMMENT '租户ID',
project_code VARCHAR(50) NOT NULL COMMENT '项目编码',
project_name VARCHAR(100) NOT NULL COMMENT '项目名称',
project_desc VARCHAR(255) NULL COMMENT '项目描述',
project_status VARCHAR(50) NOT NULL DEFAULT 'ENABLED' COMMENT '项目状态ENABLED-启用DISABLED-禁用',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
-- 索引
INDEX idx_tenant_id (tenant_id) COMMENT '租户ID索引',
UNIQUE INDEX uk_project_code (tenant_id, project_code) COMMENT '租户下项目编码唯一',
-- 外键约束
CONSTRAINT fk_project_tenant FOREIGN KEY (tenant_id)
REFERENCES sys_tenant (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目组表';
-- 应用表
CREATE TABLE deploy_application
(
-- 基础字段
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_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除0-未删除1-已删除',
-- 业务字段
project_id BIGINT NOT NULL COMMENT '所属项目ID',
app_code VARCHAR(50) NOT NULL COMMENT '应用编码',
app_name VARCHAR(100) NOT NULL COMMENT '应用名称',
app_desc VARCHAR(255) NULL COMMENT '应用描述',
app_status VARCHAR(50) NOT NULL DEFAULT 'ENABLED' COMMENT '应用状态ENABLED-启用DISABLED-禁用',
repo_url VARCHAR(255) NULL COMMENT '代码仓库地址',
repo_branch VARCHAR(100) NULL COMMENT '代码仓库分支',
repo_type VARCHAR(50) NULL COMMENT '代码仓库类型GIT、SVN',
build_type VARCHAR(50) NULL COMMENT '构建类型MAVEN、GRADLE、NPM',
dev_language VARCHAR(50) NULL COMMENT '开发语言JAVA、PYTHON、NODEJS',
dev_framework VARCHAR(50) NULL COMMENT '开发框架SPRING_BOOT、DJANGO、EXPRESS',
sort INT NOT NULL DEFAULT 0 COMMENT '排序号',
-- 索引
INDEX idx_project_id (project_id) COMMENT '项目ID索引',
UNIQUE INDEX uk_app_code (project_id, app_code) COMMENT '项目下应用编码唯一',
-- 外键约束
CONSTRAINT fk_application_project FOREIGN KEY (project_id)
REFERENCES deploy_project (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应用表';

View File

@ -73,12 +73,15 @@ VALUES
-- 节点管理 -- 节点管理
(103, '节点管理', '/workflow/node-design', '/src/pages/workflow/nodedesign/design/index', 'ControlOutlined', 2, 100, 40, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE), (103, '节点管理', '/workflow/node-design', '/src/pages/workflow/nodedesign/design/index', 'ControlOutlined', 2, 100, 40, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE),
-- 项目管理
(300, '项目管理', '/project', 'Layout', 'ProjectOutlined', 1, NULL, 4, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE),
-- 项目组列表
(301, '项目组列表', '/project/list', '/src/pages/project/list/index', 'UnorderedListOutlined', 2, 300, 10, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE),
-- 应用管理 -- 应用管理
(200, '应用管理', '/application', 'Layout', 'AppstoreOutlined', 1, NULL, 3, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE), (400, '应用管理', '/application', 'Layout', 'AppstoreOutlined', 1, NULL, 5, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE),
-- 应用列表 -- 应用列表
(201, '应用列表', '/application/list', '/src/pages/application/list/index', 'UnorderedListOutlined', 2, 200, 10, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE), (401, '应用列表', '/application/list', '/src/pages/application/list/index', 'UnorderedListOutlined', 2, 400, 10, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE);
-- 环境管理
(202, '环境管理', '/application/environment', '/src/pages/application/environment/index', 'CloudOutlined', 2, 200, 20, FALSE, TRUE, 'system', '2024-01-01 00:00:00', 0, FALSE);
-- 初始化角色数据 -- 初始化角色数据
INSERT INTO sys_role (id, create_time, code, name, type, description, sort) INSERT INTO sys_role (id, create_time, code, name, type, description, sort)
@ -846,4 +849,42 @@ INSERT INTO workflow_definition (
# } # }
# } # }
# } # }
# }', 1); # }', 1);
-- --------------------------------------------------------------------------------------
-- 初始化项目管理数据
-- --------------------------------------------------------------------------------------
-- 初始化项目组数据
INSERT INTO deploy_project (id, create_by, create_time, tenant_id, project_code, project_name, project_desc, project_status, sort)
VALUES
(1, 'admin', NOW(), 1, 'DEMO', '示例项目组', '用于演示的项目组', 'ENABLED', 1),
(2, 'admin', NOW(), 1, 'PLATFORM', '平台项目组', '平台相关的项目组', 'ENABLED', 2);
-- 初始化应用数据
INSERT INTO deploy_application (
id, create_by, create_time,
project_id, app_code, app_name, app_desc, app_status,
repo_url, repo_branch, repo_type, build_type, dev_language, dev_framework, sort
)
VALUES
(
1, 'admin', NOW(),
1, 'DEMO-APP', '示例应用', '用于演示的应用', 'ENABLED',
'https://github.com/demo/demo-app.git', 'main', 'GIT', 'MAVEN', 'JAVA', 'SPRING_BOOT', 1
),
(
2, 'admin', NOW(),
1, 'DEMO-WEB', '示例前端', '用于演示的前端应用', 'ENABLED',
'https://github.com/demo/demo-web.git', 'main', 'GIT', 'NPM', 'NODEJS', 'VUE', 2
),
(
3, 'admin', NOW(),
2, 'PLATFORM-API', '平台API', '平台后端服务', 'ENABLED',
'https://github.com/platform/platform-api.git', 'main', 'GIT', 'MAVEN', 'JAVA', 'SPRING_BOOT', 1
),
(
4, 'admin', NOW(),
2, 'PLATFORM-WEB', '平台前端', '平台前端应用', 'ENABLED',
'https://github.com/platform/platform-web.git', 'main', 'GIT', 'NPM', 'NODEJS', 'VUE', 2
);