From 42a8609b8c582975b8fb01110d35fc79cdb16ad1 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Fri, 24 Oct 2025 14:54:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0form=E8=A1=A8=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/WorkflowCategoryApiController.java | 33 +++++ .../converter/WorkflowCategoryConverter.java | 17 +++ .../backend/workflow/dto/FormDataDTO.java | 17 ++- .../workflow/dto/FormDefinitionDTO.java | 6 +- .../workflow/dto/WorkflowCategoryDTO.java | 55 +++++++- .../workflow/dto/WorkflowDefinitionDTO.java | 10 +- .../backend/workflow/dto/form/FormSchema.java | 79 ----------- .../workflow/dto/query/FormDataQuery.java | 6 + .../dto/query/WorkflowCategoryQuery.java | 37 +++++ .../dto/query/WorkflowDefinitionQuery.java | 17 ++- .../backend/workflow/entity/FormData.java | 14 +- .../workflow/entity/FormDefinition.java | 9 +- .../workflow/entity/WorkflowCategory.java | 69 +++++++++ .../workflow/entity/WorkflowDefinition.java | 8 +- .../entity/converter/FormSchemaType.java | 131 ------------------ .../workflow/enums/WorkflowCategoryEnum.java | 72 ---------- .../IWorkflowCategoryRepository.java | 24 ++++ .../service/IWorkflowCategoryService.java | 16 +++ .../service/IWorkflowDefinitionService.java | 1 - .../service/impl/FormDataServiceImpl.java | 1 + .../impl/FormDefinitionServiceImpl.java | 45 ++++++ .../impl/WorkflowCategoryServiceImpl.java | 21 +++ .../impl/WorkflowDefinitionServiceImpl.java | 30 ++-- .../db/changelog/changes/v1.0.0-data.sql | 17 ++- .../db/changelog/changes/v1.0.0-schema.sql | 49 ++++++- 25 files changed, 443 insertions(+), 341 deletions(-) create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowCategoryApiController.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowCategoryConverter.java delete mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/form/FormSchema.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/WorkflowCategoryQuery.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowCategory.java delete mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/converter/FormSchemaType.java delete mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowCategoryEnum.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowCategoryRepository.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowCategoryService.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowCategoryServiceImpl.java diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowCategoryApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowCategoryApiController.java new file mode 100644 index 00000000..262d3575 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/api/WorkflowCategoryApiController.java @@ -0,0 +1,33 @@ +package com.qqchen.deploy.backend.workflow.api; + +import com.qqchen.deploy.backend.framework.controller.BaseController; +import com.qqchen.deploy.backend.workflow.dto.WorkflowCategoryDTO; +import com.qqchen.deploy.backend.workflow.dto.query.WorkflowCategoryQuery; +import com.qqchen.deploy.backend.workflow.entity.WorkflowCategory; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 工作流分类API Controller + * + * @author qqchen + * @date 2025-10-24 + */ +@Slf4j +@RestController +@RequestMapping("/api/v1/workflow/categories") +@Tag(name = "工作流分类管理", description = "工作流分类相关接口") +public class WorkflowCategoryApiController extends BaseController { + + @Override + protected void exportData(HttpServletResponse response, List data) { + // TODO: 实现工作流分类数据导出逻辑 + log.warn("工作流分类数据导出功能暂未实现"); + } +} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowCategoryConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowCategoryConverter.java new file mode 100644 index 00000000..5828f59b --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/converter/WorkflowCategoryConverter.java @@ -0,0 +1,17 @@ +package com.qqchen.deploy.backend.workflow.converter; + +import com.qqchen.deploy.backend.framework.converter.BaseConverter; +import com.qqchen.deploy.backend.workflow.dto.WorkflowCategoryDTO; +import com.qqchen.deploy.backend.workflow.entity.WorkflowCategory; +import org.mapstruct.Mapper; + +/** + * 工作流分类转换器 + * + * @author qqchen + * @date 2025-10-24 + */ +@Mapper(config = BaseConverter.class) +public interface WorkflowCategoryConverter extends BaseConverter { +} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/FormDataDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/FormDataDTO.java index c5d68ad8..4205c8c8 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/FormDataDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/FormDataDTO.java @@ -1,7 +1,6 @@ package com.qqchen.deploy.backend.workflow.dto; import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.workflow.dto.form.FormSchema; import com.qqchen.deploy.backend.workflow.enums.FormBusinessTypeEnums; import com.qqchen.deploy.backend.workflow.enums.FormDataStatusEnums; import io.swagger.v3.oas.annotations.media.Schema; @@ -40,6 +39,18 @@ public class FormDataDTO extends BaseDTO { @Schema(description = "表单版本", example = "1") private Integer formVersion; + /** + * 表单分类ID(冗余存储,便于统计和查询) + */ + @Schema(description = "表单分类ID", example = "1") + private Long categoryId; + + /** + * 表单分类信息(用于展示) + */ + @Schema(description = "表单分类信息") + private FormCategoryDTO category; + /** * 业务标识(如工作流实例ID、订单号等) */ @@ -59,10 +70,10 @@ public class FormDataDTO extends BaseDTO { private Map data; /** - * 表单Schema快照(用于历史追溯,确保数据可还原) + * 表单Schema快照(用于历史追溯,确保数据可还原,原样存储) */ @Schema(description = "表单Schema快照") - private FormSchema schemaSnapshot; + private Map schemaSnapshot; /** * 提交人 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/FormDefinitionDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/FormDefinitionDTO.java index f6e8b7da..fa05c2be 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/FormDefinitionDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/FormDefinitionDTO.java @@ -1,13 +1,13 @@ package com.qqchen.deploy.backend.workflow.dto; import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.workflow.dto.form.FormSchema; import com.qqchen.deploy.backend.workflow.enums.FormDefinitionStatusEnums; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import java.util.List; +import java.util.Map; /** * 表单定义DTO @@ -57,10 +57,10 @@ public class FormDefinitionDTO extends BaseDTO { private String description; /** - * 表单Schema(前端设计器导出的JSON结构) + * 表单Schema(前端设计器导出的JSON结构,原样存储) */ @Schema(description = "表单Schema") - private FormSchema schema; + private Map schema; /** * 标签(用于分类和搜索) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowCategoryDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowCategoryDTO.java index ca3227b6..03d1d8a5 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowCategoryDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowCategoryDTO.java @@ -1,19 +1,64 @@ package com.qqchen.deploy.backend.workflow.dto; - +import com.qqchen.deploy.backend.framework.dto.BaseDTO; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.EqualsAndHashCode; import java.util.List; +/** + * 工作流分类DTO + * + * @author qqchen + * @date 2025-10-24 + */ @Data -public class WorkflowCategoryDTO { +@EqualsAndHashCode(callSuper = true) +@Schema(description = "工作流分类DTO") +public class WorkflowCategoryDTO extends BaseDTO { + private Long id; + + /** + * 分类名称 + */ + @Schema(description = "分类名称", example = "脚本执行") + private String name; + + /** + * 分类编码(唯一) + */ + @Schema(description = "分类编码", example = "SCRIPT_EXECUTION") private String code; - private String lable; - + /** + * 分类描述 + */ + @Schema(description = "分类描述", example = "用于执行各类脚本的流程") private String description; - private List supportedTriggers; + /** + * 图标 + */ + @Schema(description = "图标", example = "CodeOutlined") + private String icon; + /** + * 排序 + */ + @Schema(description = "排序", example = "1") + private Integer sort; + + /** + * 支持的触发方式列表 + */ + @Schema(description = "支持的触发方式列表", example = "[\"MANUAL\",\"SCHEDULED\"]") + private List supportedTriggers; + + /** + * 是否启用 + */ + @Schema(description = "是否启用", example = "true") + private Boolean enabled; } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDefinitionDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDefinitionDTO.java index 3ba3d323..b0e06882 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDefinitionDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/WorkflowDefinitionDTO.java @@ -3,7 +3,6 @@ package com.qqchen.deploy.backend.workflow.dto; import com.fasterxml.jackson.databind.JsonNode; import com.qqchen.deploy.backend.framework.dto.BaseDTO; import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraph; -import com.qqchen.deploy.backend.workflow.enums.WorkflowCategoryEnum; import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnums; import com.qqchen.deploy.backend.workflow.enums.WorkflowTriggerTypeEnum; import lombok.Data; @@ -32,9 +31,14 @@ public class WorkflowDefinitionDTO extends BaseDTO { private String key; /** - * 分类 + * 分类ID */ - private WorkflowCategoryEnum category; + private Long categoryId; + + /** + * 分类信息(用于展示) + */ + private WorkflowCategoryDTO category; /** * 触发类型列表 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/form/FormSchema.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/form/FormSchema.java deleted file mode 100644 index acbcb5dc..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/form/FormSchema.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.qqchen.deploy.backend.workflow.dto.form; - -import lombok.Data; - -import java.util.List; -import java.util.Map; - -/** - * 表单Schema定义 - * 用于存储前端表单设计器导出的JSON结构 - * - * @author qqchen - * @date 2025-10-24 - */ -@Data -public class FormSchema { - - /** - * 表单标题 - */ - private String title; - - /** - * 表单描述 - */ - private String description; - - /** - * 表单字段列表 - */ - private List fields; - - /** - * 表单配置 - */ - private Map config; - - /** - * 表单字段定义 - */ - @Data - public static class FormField { - /** - * 字段名称 - */ - private String name; - - /** - * 字段标签 - */ - private String label; - - /** - * 字段类型(input、select、textarea、date、number等) - */ - private String type; - - /** - * 是否必填 - */ - private Boolean required; - - /** - * 默认值 - */ - private Object defaultValue; - - /** - * 字段配置(不同类型字段有不同配置) - */ - private Map config; - - /** - * 验证规则 - */ - private List> validators; - } -} - diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/FormDataQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/FormDataQuery.java index 5df5abfe..39207b6c 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/FormDataQuery.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/FormDataQuery.java @@ -30,6 +30,12 @@ public class FormDataQuery extends BaseQuery { @QueryField(field = "formKey", type = QueryType.EQUAL) private String formKey; + /** + * 表单分类ID(精确查询) + */ + @QueryField(field = "categoryId", type = QueryType.EQUAL) + private Long categoryId; + /** * 业务标识(精确查询) */ diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/WorkflowCategoryQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/WorkflowCategoryQuery.java new file mode 100644 index 00000000..c91087f6 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/WorkflowCategoryQuery.java @@ -0,0 +1,37 @@ +package com.qqchen.deploy.backend.workflow.dto.query; + +import com.qqchen.deploy.backend.framework.annotation.QueryField; +import com.qqchen.deploy.backend.framework.enums.QueryType; +import com.qqchen.deploy.backend.framework.query.BaseQuery; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 工作流分类查询对象 + * + * @author qqchen + * @date 2025-10-24 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class WorkflowCategoryQuery extends BaseQuery { + + /** + * 分类名称(模糊查询) + */ + @QueryField(field = "name", type = QueryType.LIKE) + private String name; + + /** + * 分类编码(精确查询) + */ + @QueryField(field = "code", type = QueryType.EQUAL) + private String code; + + /** + * 是否启用(精确查询) + */ + @QueryField(field = "enabled", type = QueryType.EQUAL) + private Boolean enabled; +} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/WorkflowDefinitionQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/WorkflowDefinitionQuery.java index 4aca4808..8c76187d 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/WorkflowDefinitionQuery.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/dto/query/WorkflowDefinitionQuery.java @@ -3,6 +3,7 @@ package com.qqchen.deploy.backend.workflow.dto.query; import com.qqchen.deploy.backend.framework.annotation.QueryField; import com.qqchen.deploy.backend.framework.enums.QueryType; import com.qqchen.deploy.backend.framework.query.BaseQuery; +import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnums; import lombok.Data; import lombok.EqualsAndHashCode; @@ -25,9 +26,21 @@ public class WorkflowDefinitionQuery extends BaseQuery { @QueryField(field = "key", type = QueryType.EQUAL) private String key; + /** + * 分类ID + */ + @QueryField(field = "categoryId", type = QueryType.EQUAL) + private Long categoryId; + /** * 流程版本 */ - @QueryField(field = "version", type = QueryType.EQUAL) - private Integer version; + @QueryField(field = "flowVersion", type = QueryType.EQUAL) + private Integer flowVersion; + + /** + * 流程状态 + */ + @QueryField(field = "status", type = QueryType.EQUAL) + private WorkflowDefinitionStatusEnums status; } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/FormData.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/FormData.java index 92b7da68..652d0ba8 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/FormData.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/FormData.java @@ -2,8 +2,6 @@ package com.qqchen.deploy.backend.workflow.entity; import com.qqchen.deploy.backend.framework.annotation.LogicDelete; import com.qqchen.deploy.backend.framework.domain.Entity; -import com.qqchen.deploy.backend.workflow.dto.form.FormSchema; -import com.qqchen.deploy.backend.workflow.entity.converter.FormSchemaType; import com.qqchen.deploy.backend.workflow.enums.FormBusinessTypeEnums; import com.qqchen.deploy.backend.workflow.enums.FormDataStatusEnums; import com.vladmihalcea.hibernate.type.json.JsonType; @@ -46,6 +44,12 @@ public class FormData extends Entity { @Column(name = "form_version", nullable = false) private Integer formVersion; + /** + * 表单分类ID(冗余存储,便于统计和查询) + */ + @Column(name = "category_id") + private Long categoryId; + /** * 业务标识(如工作流实例ID、订单号等) */ @@ -67,11 +71,11 @@ public class FormData extends Entity { private Map data; /** - * 表单Schema快照(用于历史追溯,确保数据可还原) + * 表单Schema快照(用于历史追溯,确保数据可还原,原样存储) */ - @Type(FormSchemaType.class) + @Type(JsonType.class) @Column(name = "schema_snapshot", nullable = false, columnDefinition = "json") - private FormSchema schemaSnapshot; + private Map schemaSnapshot; /** * 提交人 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/FormDefinition.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/FormDefinition.java index 9164b893..d47b67e4 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/FormDefinition.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/FormDefinition.java @@ -2,8 +2,6 @@ package com.qqchen.deploy.backend.workflow.entity; import com.qqchen.deploy.backend.framework.annotation.LogicDelete; import com.qqchen.deploy.backend.framework.domain.Entity; -import com.qqchen.deploy.backend.workflow.dto.form.FormSchema; -import com.qqchen.deploy.backend.workflow.entity.converter.FormSchemaType; import com.qqchen.deploy.backend.workflow.enums.FormDefinitionStatusEnums; import com.vladmihalcea.hibernate.type.json.JsonType; import jakarta.persistence.*; @@ -12,6 +10,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; import java.util.List; +import java.util.Map; /** * 表单定义实体 @@ -57,11 +56,11 @@ public class FormDefinition extends Entity { private String description; /** - * 表单Schema(前端设计器导出的JSON结构) + * 表单Schema(前端设计器导出的JSON结构,原样存储) */ - @Type(FormSchemaType.class) + @Type(JsonType.class) @Column(name = "`schema`", nullable = false, columnDefinition = "json") - private FormSchema schema; + private Map schema; /** * 标签(用于分类和搜索) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowCategory.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowCategory.java new file mode 100644 index 00000000..d33d89b5 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowCategory.java @@ -0,0 +1,69 @@ +package com.qqchen.deploy.backend.workflow.entity; + +import com.qqchen.deploy.backend.framework.annotation.LogicDelete; +import com.qqchen.deploy.backend.framework.domain.Entity; +import com.vladmihalcea.hibernate.type.json.JsonType; +import jakarta.persistence.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.hibernate.annotations.Type; + +import java.util.List; + +/** + * 工作流分类实体 + * + * @author qqchen + * @date 2025-10-24 + */ +@Data +@Table(name = "workflow_category") +@jakarta.persistence.Entity +@EqualsAndHashCode(callSuper = true) +@LogicDelete +public class WorkflowCategory extends Entity { + + /** + * 分类名称 + */ + @Column(name = "name", nullable = false, length = 100) + private String name; + + /** + * 分类编码(唯一,如SCRIPT_EXECUTION) + */ + @Column(name = "code", nullable = false, length = 50, unique = true) + private String code; + + /** + * 分类描述 + */ + @Column(name = "description", length = 500) + private String description; + + /** + * 图标 + */ + @Column(name = "icon", length = 50) + private String icon; + + /** + * 排序 + */ + @Column(name = "sort", nullable = false) + private Integer sort = 0; + + /** + * 支持的触发方式列表(JSON数组,如["MANUAL","SCHEDULED"]) + */ + @Type(JsonType.class) + @Column(name = "supported_triggers", columnDefinition = "json") + private List supportedTriggers; + + /** + * 是否启用 + */ + @Column(name = "enabled", nullable = false) + private Boolean enabled = true; +} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowDefinition.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowDefinition.java index 82deb7c0..6e39d81a 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowDefinition.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowDefinition.java @@ -3,7 +3,6 @@ package com.qqchen.deploy.backend.workflow.entity; import com.fasterxml.jackson.databind.JsonNode; import com.qqchen.deploy.backend.framework.annotation.LogicDelete; import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraph; -import com.qqchen.deploy.backend.workflow.enums.WorkflowCategoryEnum; import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnums; import com.qqchen.deploy.backend.workflow.enums.WorkflowTriggerTypeEnum; import com.qqchen.deploy.backend.workflow.entity.converter.WorkflowGraphType; @@ -43,11 +42,10 @@ public class WorkflowDefinition extends Entity { private String key; /** - * 流程分类 + * 流程分类ID(外键关联workflow_category) */ - @Column(name = "category", nullable = false) - @Enumerated(EnumType.STRING) - private WorkflowCategoryEnum category; + @Column(name = "category_id") + private Long categoryId; @Column(name = "triggers", nullable = false) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/converter/FormSchemaType.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/converter/FormSchemaType.java deleted file mode 100644 index 0e000d88..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/converter/FormSchemaType.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.qqchen.deploy.backend.workflow.entity.converter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.qqchen.deploy.backend.workflow.dto.form.FormSchema; -import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.usertype.UserType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Serializable; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; - -/** - * 自定义 Hibernate 类型,用于处理 FormSchema 的序列化和反序列化 - * - * @author qqchen - * @date 2025-10-24 - */ -public class FormSchemaType implements UserType { - private static final Logger log = LoggerFactory.getLogger(FormSchemaType.class); - private final ObjectMapper objectMapper; - - public FormSchemaType() { - this.objectMapper = new ObjectMapper(); - // 配置 ObjectMapper,忽略未知属性 - this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - } - - @Override - public int getSqlType() { - return Types.VARCHAR; - } - - @Override - public Class returnedClass() { - return FormSchema.class; - } - - @Override - public boolean equals(FormSchema x, FormSchema y) { - if (x == y) { - return true; - } - if (x == null || y == null) { - return false; - } - return x.equals(y); - } - - @Override - public int hashCode(FormSchema x) { - return x == null ? 0 : x.hashCode(); - } - - @Override - public FormSchema nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) - throws SQLException { - String value = rs.getString(position); - if (value == null) { - return null; - } - try { - return objectMapper.readValue(value, FormSchema.class); - } catch (JsonProcessingException e) { - // 记录错误日志,但不抛出异常,返回 null 使得单条记录的错误不影响整体查询 - log.error("Failed to convert String to FormSchema: " + value, e); - return null; - } - } - - @Override - public void nullSafeSet(PreparedStatement st, FormSchema value, int index, SharedSessionContractImplementor session) - throws SQLException { - if (value == null) { - st.setNull(index, Types.VARCHAR); - return; - } - try { - st.setString(index, objectMapper.writeValueAsString(value)); - } catch (JsonProcessingException e) { - throw new HibernateException("Failed to convert FormSchema to String: " + value, e); - } - } - - @Override - public FormSchema deepCopy(FormSchema value) { - if (value == null) { - return null; - } - try { - return objectMapper.readValue(objectMapper.writeValueAsString(value), FormSchema.class); - } catch (JsonProcessingException e) { - throw new HibernateException("Failed to deep copy FormSchema", e); - } - } - - @Override - public boolean isMutable() { - return true; - } - - @Override - public Serializable disassemble(FormSchema value) { - try { - return value == null ? null : objectMapper.writeValueAsString(value); - } catch (JsonProcessingException e) { - throw new HibernateException("Failed to disassemble FormSchema", e); - } - } - - @Override - public FormSchema assemble(Serializable cached, Object owner) { - try { - return cached == null ? null : objectMapper.readValue(cached.toString(), FormSchema.class); - } catch (JsonProcessingException e) { - throw new HibernateException("Failed to assemble FormSchema", e); - } - } - - @Override - public FormSchema replace(FormSchema detached, FormSchema managed, Object owner) { - return deepCopy(detached); - } -} - diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowCategoryEnum.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowCategoryEnum.java deleted file mode 100644 index 720e22a3..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/enums/WorkflowCategoryEnum.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.qqchen.deploy.backend.workflow.enums; - - -import lombok.Getter; - -import java.util.Arrays; -import java.util.List; - -/** - * 工作流节点分类枚举 - */ -@Getter -public enum WorkflowCategoryEnum { - // 1. 脚本执行类 - SCRIPT_EXECUTION( - "脚本执行", - "用于执行各类脚本的流程", - Arrays.asList(WorkflowTriggerTypeEnum.MANUAL, WorkflowTriggerTypeEnum.SCHEDULED) - ), - - // 2. 部署类 - DEPLOYMENT( - "应用部署", - "用于应用部署的流程", - Arrays.asList(WorkflowTriggerTypeEnum.MANUAL, WorkflowTriggerTypeEnum.SCHEDULED, WorkflowTriggerTypeEnum.APPROVAL) - ), - - // 3. 数据同步类 - DATA_SYNC( - "数据同步", - "用于第三方系统数据同步的流程", - Arrays.asList(WorkflowTriggerTypeEnum.MANUAL, WorkflowTriggerTypeEnum.SCHEDULED) - ), - - // 4. 配置同步类 - CONFIG_SYNC( - "配置同步", - "用于配置中心数据同步的流程", - Arrays.asList(WorkflowTriggerTypeEnum.MANUAL, WorkflowTriggerTypeEnum.APPROVAL) - ), - - // 5. 审批流程类 - APPROVAL( - "审批流程", - "纯审批流程", - Arrays.asList(WorkflowTriggerTypeEnum.MANUAL) - ), - - // 6. 其他类型(用于扩展) - OTHER( - "其他", - "其他类型流程", - Arrays.asList(WorkflowTriggerTypeEnum.MANUAL) - ); - - private final String label; // 显示名称 - - private final String description; // 描述 - - private final List supportedTriggers; // 支持的触发方式 - - WorkflowCategoryEnum(String label, String description, List supportedTriggers) { - this.label = label; - this.description = description; - this.supportedTriggers = supportedTriggers; - } - - // 判断是否支持某种触发方式 - public boolean supportsTriggerType(WorkflowTriggerTypeEnum triggerType) { - return supportedTriggers.contains(triggerType); - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowCategoryRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowCategoryRepository.java new file mode 100644 index 00000000..0ee22389 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/repository/IWorkflowCategoryRepository.java @@ -0,0 +1,24 @@ +package com.qqchen.deploy.backend.workflow.repository; + +import com.qqchen.deploy.backend.framework.repository.IBaseRepository; +import com.qqchen.deploy.backend.workflow.entity.WorkflowCategory; +import org.springframework.stereotype.Repository; + +/** + * 工作流分类Repository + * + * @author qqchen + * @date 2025-10-24 + */ +@Repository +public interface IWorkflowCategoryRepository extends IBaseRepository { + + /** + * 根据编码查询分类 + * + * @param code 分类编码 + * @return 工作流分类 + */ + WorkflowCategory findByCodeAndDeletedFalse(String code); +} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowCategoryService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowCategoryService.java new file mode 100644 index 00000000..e26ed901 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowCategoryService.java @@ -0,0 +1,16 @@ +package com.qqchen.deploy.backend.workflow.service; + +import com.qqchen.deploy.backend.framework.service.IBaseService; +import com.qqchen.deploy.backend.workflow.dto.WorkflowCategoryDTO; +import com.qqchen.deploy.backend.workflow.dto.query.WorkflowCategoryQuery; +import com.qqchen.deploy.backend.workflow.entity.WorkflowCategory; + +/** + * 工作流分类Service接口 + * + * @author qqchen + * @date 2025-10-24 + */ +public interface IWorkflowCategoryService extends IBaseService { +} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDefinitionService.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDefinitionService.java index 95e93e0c..3c9e6eb0 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDefinitionService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/IWorkflowDefinitionService.java @@ -9,7 +9,6 @@ import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceCreateDTO; import com.qqchen.deploy.backend.workflow.dto.WorkflowInstanceDTO; import com.qqchen.deploy.backend.workflow.dto.query.WorkflowDefinitionQuery; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import com.qqchen.deploy.backend.workflow.enums.WorkflowCategoryEnum; import org.flowable.engine.repository.Deployment; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.transaction.annotation.Transactional; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/FormDataServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/FormDataServiceImpl.java index 6b8dcbb8..b2d34163 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/FormDataServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/FormDataServiceImpl.java @@ -50,6 +50,7 @@ public class FormDataServiceImpl extends BaseServiceImpl new BusinessException(com.qqchen.deploy.backend.framework.enums.ResponseCode.FORM_DEFINITION_NOT_FOUND)); + + // 2. 保留后端控制的字段(版本号和状态由后端控制,不允许前端修改) + Integer originalFormVersion = existingForm.getFormVersion(); + FormDefinitionStatusEnums originalStatus = existingForm.getStatus(); + + // 3. 转换并更新允许修改的字段 + FormDefinition formDefinition = formDefinitionConverter.toEntity(dto); + formDefinition.setId(id); // 使用路径参数的ID + formDefinition.setFormVersion(originalFormVersion); // 保留原始版本号 + formDefinition.setStatus(originalStatus); // 保留原始状态 + + // 4. 保存 + FormDefinition savedForm = formDefinitionRepository.save(formDefinition); + log.info("表单定义更新成功: id={}, version={}, status={}", savedForm.getId(), savedForm.getFormVersion(), savedForm.getStatus()); + + return formDefinitionConverter.toDto(savedForm); + } + @Override @Transactional public FormDefinitionDTO publish(Long id) { diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowCategoryServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowCategoryServiceImpl.java new file mode 100644 index 00000000..313903a9 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowCategoryServiceImpl.java @@ -0,0 +1,21 @@ +package com.qqchen.deploy.backend.workflow.service.impl; + +import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; +import com.qqchen.deploy.backend.workflow.dto.WorkflowCategoryDTO; +import com.qqchen.deploy.backend.workflow.dto.query.WorkflowCategoryQuery; +import com.qqchen.deploy.backend.workflow.entity.WorkflowCategory; +import com.qqchen.deploy.backend.workflow.service.IWorkflowCategoryService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 工作流分类Service实现 + * + * @author qqchen + * @date 2025-10-24 + */ +@Slf4j +@Service +public class WorkflowCategoryServiceImpl extends BaseServiceImpl implements IWorkflowCategoryService { +} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDefinitionServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDefinitionServiceImpl.java index 5d84ba33..bfd71fdd 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDefinitionServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/service/impl/WorkflowDefinitionServiceImpl.java @@ -8,7 +8,6 @@ import com.qqchen.deploy.backend.workflow.dto.WorkflowTriggerTypeDTO; import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraph; import com.qqchen.deploy.backend.workflow.dto.query.WorkflowDefinitionQuery; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; -import com.qqchen.deploy.backend.workflow.enums.WorkflowCategoryEnum; import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnums; import com.qqchen.deploy.backend.workflow.enums.WorkflowNodeInstanceStatusEnums; import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository; @@ -68,6 +67,11 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl getWorkflowCategories() { - return Arrays.stream(WorkflowCategoryEnum.values()) - .map(category -> { - WorkflowCategoryDTO dto = new WorkflowCategoryDTO(); - dto.setCode(category.name()); - dto.setLable(category.getLabel()); - dto.setDescription(category.getDescription()); - // 获取该类别支持的触发方式 - dto.setSupportedTriggers( - category.getSupportedTriggers().stream() - .map(triggerType -> { - WorkflowTriggerTypeDTO triggerDto = new WorkflowTriggerTypeDTO(); - triggerDto.setCode(triggerType.name()); - triggerDto.setLable(triggerType.getLabel()); - return triggerDto; - }) - .collect(Collectors.toList()) - ); - return dto; - }) + // 从数据库查询启用的工作流分类,按排序字段排序 + return workflowCategoryRepository.findAll().stream() + .filter(category -> category.getEnabled() && !category.getDeleted()) + .sorted((a, b) -> a.getSort().compareTo(b.getSort())) + .map(workflowCategoryConverter::toDto) .collect(Collectors.toList()); } diff --git a/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql b/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql index 2efe7b6b..f7b848a1 100644 --- a/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql +++ b/backend/src/main/resources/db/changelog/changes/v1.0.0-data.sql @@ -219,10 +219,21 @@ INSERT INTO sys_external_system ( -- -------------------------------------------------------------------------------------- -- 初始化工作流相关数据 -- -------------------------------------------------------------------------------------- + +-- 工作流分类初始数据 +INSERT INTO workflow_category (name, code, description, icon, sort, supported_triggers, enabled, create_by, create_time, update_by, update_time, version, deleted) +VALUES +('脚本执行', 'SCRIPT_EXECUTION', '用于执行各类脚本的流程', 'CodeOutlined', 1, '["MANUAL","SCHEDULED"]', 1, 'system', NOW(), 'system', NOW(), 0, 0), +('应用部署', 'DEPLOYMENT', '用于应用部署的流程', 'DeploymentUnitOutlined', 2, '["MANUAL","SCHEDULED","APPROVAL"]', 1, 'system', NOW(), 'system', NOW(), 0, 0), +('数据同步', 'DATA_SYNC', '用于第三方系统数据同步的流程', 'SyncOutlined', 3, '["MANUAL","SCHEDULED"]', 1, 'system', NOW(), 'system', NOW(), 0, 0), +('配置同步', 'CONFIG_SYNC', '用于配置中心数据同步的流程', 'SettingOutlined', 4, '["MANUAL","APPROVAL"]', 1, 'system', NOW(), 'system', NOW(), 0, 0), +('审批流程', 'APPROVAL', '纯审批流程', 'AuditOutlined', 5, '["MANUAL"]', 1, 'system', NOW(), 'system', NOW(), 0, 0), +('其他', 'OTHER', '其他类型流程', 'AppstoreOutlined', 99, '["MANUAL"]', 1, 'system', NOW(), 'system', NOW(), 0, 0); + -- 工作流定义测试数据 INSERT INTO workflow_definition ( -- 基础信息 - name, `key`, process_definition_id, flow_version, description, category, triggers, + name, `key`, process_definition_id, flow_version, description, category_id, triggers, -- 流程配置 graph, tags, -- 流程属性 @@ -232,7 +243,7 @@ INSERT INTO workflow_definition ( ) VALUES -- 简单脚本流程:开始 -> 脚本任务 -> 结束 ( - '简单脚本流程', 'simple_script_flow', null, 1, '一个包含脚本任务的简单流程', 'SCRIPT_EXECUTION', null, + '简单脚本流程', 'simple_script_flow', null, 1, '一个包含脚本任务的简单流程', 1, null, '{ "nodes" : [ { "id" : "startEvent1", @@ -400,7 +411,7 @@ INSERT INTO workflow_definition ( -- 复杂业务流程:开始 -> 脚本任务A -> 脚本任务B -> 结束 ( - '复杂业务流程', 'complex_business_flow', null, 1, '包含多个脚本任务节点的业务流程', 'SCRIPT_EXECUTION', null, + '复杂业务流程', 'complex_business_flow', null, 1, '包含多个脚本任务节点的业务流程', 1, null, '{ "nodes" : [ { "id" : "startEvent1", diff --git a/backend/src/main/resources/db/changelog/changes/v1.0.0-schema.sql b/backend/src/main/resources/db/changelog/changes/v1.0.0-schema.sql index d3af6845..f0934f70 100644 --- a/backend/src/main/resources/db/changelog/changes/v1.0.0-schema.sql +++ b/backend/src/main/resources/db/changelog/changes/v1.0.0-schema.sql @@ -371,6 +371,41 @@ 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"]) + 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 '是否删除', + update_by VARCHAR(255) NULL COMMENT '更新人', + update_time DATETIME(6) NULL COMMENT '更新时间', + version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + + -- 约束和索引 + UNIQUE KEY uk_code (code), + INDEX idx_enabled (enabled), + INDEX idx_deleted (deleted), + INDEX idx_sort (sort) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci + COMMENT = '工作流分类表'; + -- 工作流定义表 CREATE TABLE workflow_definition ( @@ -380,8 +415,8 @@ CREATE TABLE workflow_definition -- 基础信息 name VARCHAR(255) NOT NULL COMMENT '流程名称', `key` VARCHAR(255) NOT NULL COMMENT '流程标识', - category VARCHAR(100) COMMENT '流程分类', - triggers VARCHAR(200) COMMENT '流程分类', + category_id BIGINT NULL COMMENT '流程分类ID(外键关联workflow_category)', + triggers JSON NULL COMMENT '触发器配置(JSON数组)', process_definition_id VARCHAR(100) NULL COMMENT '工作流定义ID', flow_version INT NOT NULL COMMENT '流程版本', description TEXT COMMENT '流程描述', @@ -402,8 +437,12 @@ CREATE TABLE workflow_definition update_time DATETIME(6) NULL COMMENT '更新时间', version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - -- 约束 - UNIQUE KEY uk_key_version (`key`, flow_version) + -- 约束和索引 + UNIQUE KEY uk_key_version (`key`, flow_version), + INDEX idx_category_id (category_id), + INDEX idx_status (status), + INDEX idx_deleted (deleted), + CONSTRAINT fk_workflow_definition_category FOREIGN KEY (category_id) REFERENCES workflow_category(id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT ='工作流定义表'; @@ -776,6 +815,7 @@ CREATE TABLE form_data 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、订单号等)', @@ -803,6 +843,7 @@ CREATE TABLE form_data -- 索引 INDEX idx_form_definition_id (form_definition_id), INDEX idx_form_key (form_key), + INDEX idx_category_id (category_id), INDEX idx_business_key (business_key), INDEX idx_business_type (business_type), INDEX idx_submitter (submitter),