增加form表单
This commit is contained in:
parent
6d8afea807
commit
42a8609b8c
@ -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<WorkflowCategory, WorkflowCategoryDTO, Long, WorkflowCategoryQuery> {
|
||||
|
||||
@Override
|
||||
protected void exportData(HttpServletResponse response, List<WorkflowCategoryDTO> data) {
|
||||
// TODO: 实现工作流分类数据导出逻辑
|
||||
log.warn("工作流分类数据导出功能暂未实现");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<WorkflowCategory, WorkflowCategoryDTO> {
|
||||
}
|
||||
|
||||
@ -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<String, Object> data;
|
||||
|
||||
/**
|
||||
* 表单Schema快照(用于历史追溯,确保数据可还原)
|
||||
* 表单Schema快照(用于历史追溯,确保数据可还原,原样存储)
|
||||
*/
|
||||
@Schema(description = "表单Schema快照")
|
||||
private FormSchema schemaSnapshot;
|
||||
private Map<String, Object> schemaSnapshot;
|
||||
|
||||
/**
|
||||
* 提交人
|
||||
|
||||
@ -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<String, Object> schema;
|
||||
|
||||
/**
|
||||
* 标签(用于分类和搜索)
|
||||
|
||||
@ -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<WorkflowTriggerTypeDTO> supportedTriggers;
|
||||
/**
|
||||
* 图标
|
||||
*/
|
||||
@Schema(description = "图标", example = "CodeOutlined")
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
@Schema(description = "排序", example = "1")
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 支持的触发方式列表
|
||||
*/
|
||||
@Schema(description = "支持的触发方式列表", example = "[\"MANUAL\",\"SCHEDULED\"]")
|
||||
private List<String> supportedTriggers;
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
@Schema(description = "是否启用", example = "true")
|
||||
private Boolean enabled;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
* 触发类型列表
|
||||
|
||||
@ -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<FormField> fields;
|
||||
|
||||
/**
|
||||
* 表单配置
|
||||
*/
|
||||
private Map<String, Object> 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<String, Object> config;
|
||||
|
||||
/**
|
||||
* 验证规则
|
||||
*/
|
||||
private List<Map<String, Object>> validators;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
* 业务标识(精确查询)
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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<Long> {
|
||||
@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<Long> {
|
||||
private Map<String, Object> data;
|
||||
|
||||
/**
|
||||
* 表单Schema快照(用于历史追溯,确保数据可还原)
|
||||
* 表单Schema快照(用于历史追溯,确保数据可还原,原样存储)
|
||||
*/
|
||||
@Type(FormSchemaType.class)
|
||||
@Type(JsonType.class)
|
||||
@Column(name = "schema_snapshot", nullable = false, columnDefinition = "json")
|
||||
private FormSchema schemaSnapshot;
|
||||
private Map<String, Object> schemaSnapshot;
|
||||
|
||||
/**
|
||||
* 提交人
|
||||
|
||||
@ -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<Long> {
|
||||
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<String, Object> schema;
|
||||
|
||||
/**
|
||||
* 标签(用于分类和搜索)
|
||||
|
||||
@ -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<Long> {
|
||||
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
@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<String> supportedTriggers;
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
@Column(name = "enabled", nullable = false)
|
||||
private Boolean enabled = true;
|
||||
}
|
||||
|
||||
@ -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<Long> {
|
||||
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)
|
||||
|
||||
@ -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<FormSchema> {
|
||||
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<FormSchema> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<WorkflowTriggerTypeEnum> supportedTriggers; // 支持的触发方式
|
||||
|
||||
WorkflowCategoryEnum(String label, String description, List<WorkflowTriggerTypeEnum> supportedTriggers) {
|
||||
this.label = label;
|
||||
this.description = description;
|
||||
this.supportedTriggers = supportedTriggers;
|
||||
}
|
||||
|
||||
// 判断是否支持某种触发方式
|
||||
public boolean supportsTriggerType(WorkflowTriggerTypeEnum triggerType) {
|
||||
return supportedTriggers.contains(triggerType);
|
||||
}
|
||||
}
|
||||
@ -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<WorkflowCategory, Long> {
|
||||
|
||||
/**
|
||||
* 根据编码查询分类
|
||||
*
|
||||
* @param code 分类编码
|
||||
* @return 工作流分类
|
||||
*/
|
||||
WorkflowCategory findByCodeAndDeletedFalse(String code);
|
||||
}
|
||||
|
||||
@ -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<WorkflowCategory, WorkflowCategoryDTO, WorkflowCategoryQuery, Long> {
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -50,6 +50,7 @@ public class FormDataServiceImpl extends BaseServiceImpl<FormData, FormDataDTO,
|
||||
FormData formData = formDataConverter.toEntity(dto);
|
||||
formData.setFormKey(formDefinition.getKey());
|
||||
formData.setFormVersion(formDefinition.getFormVersion());
|
||||
formData.setCategoryId(formDefinition.getCategoryId()); // 冗余存储分类ID
|
||||
formData.setSchemaSnapshot(formDefinition.getSchema()); // 保存schema快照
|
||||
formData.setSubmitTime(LocalDateTime.now());
|
||||
formData.setStatus(FormDataStatusEnums.SUBMITTED);
|
||||
|
||||
@ -30,6 +30,51 @@ public class FormDefinitionServiceImpl extends BaseServiceImpl<FormDefinition, F
|
||||
@Resource
|
||||
private FormDefinitionConverter formDefinitionConverter;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public FormDefinitionDTO create(FormDefinitionDTO dto) {
|
||||
log.info("创建表单定义: name={}, key={}", dto.getName(), dto.getKey());
|
||||
|
||||
// 1. 转换为实体
|
||||
FormDefinition formDefinition = formDefinitionConverter.toEntity(dto);
|
||||
|
||||
// 2. 后端控制版本号和状态(前端传递的值会被覆盖)
|
||||
formDefinition.setFormVersion(1); // 新建表单,版本号固定为 1
|
||||
formDefinition.setStatus(FormDefinitionStatusEnums.DRAFT); // 新建表单,状态固定为草稿
|
||||
|
||||
// 3. 保存
|
||||
FormDefinition savedForm = formDefinitionRepository.save(formDefinition);
|
||||
log.info("表单定义创建成功: id={}, key={}, version={}", savedForm.getId(), savedForm.getKey(), savedForm.getFormVersion());
|
||||
|
||||
return formDefinitionConverter.toDto(savedForm);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public FormDefinitionDTO update(Long id, FormDefinitionDTO dto) {
|
||||
log.info("更新表单定义: id={}, name={}", id, dto.getName());
|
||||
|
||||
// 1. 查询原始表单定义
|
||||
FormDefinition existingForm = formDefinitionRepository.findById(id)
|
||||
.orElseThrow(() -> 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) {
|
||||
|
||||
@ -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<WorkflowCategory, WorkflowCategoryDTO, WorkflowCategoryQuery, Long> implements IWorkflowCategoryService {
|
||||
}
|
||||
|
||||
@ -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<WorkflowDefin
|
||||
@Resource
|
||||
private IWorkflowDefinitionRepository workflowDefinitionRepository;
|
||||
|
||||
@Resource
|
||||
private com.qqchen.deploy.backend.workflow.repository.IWorkflowCategoryRepository workflowCategoryRepository;
|
||||
|
||||
@Resource
|
||||
private com.qqchen.deploy.backend.workflow.converter.WorkflowCategoryConverter workflowCategoryConverter;
|
||||
|
||||
@Resource
|
||||
private BpmnConverter bpmnConverter;
|
||||
@ -337,25 +341,11 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl<WorkflowDefin
|
||||
|
||||
@Override
|
||||
public List<WorkflowCategoryDTO> 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());
|
||||
}
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user