deploy-ease-platform/backend/readme1.md
2024-12-18 15:18:33 +08:00

11 KiB
Raw Blame History

工作流动态表单设计方案

1. 整体架构

1.1 数据流向

1. 流程设计阶段
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   表单设计器    │     │   流程设计器    │     │    后端存储     │
│  Form Designer  │ ──> │ Flow Designer   │ ──> │   Database      │
└─────────────────┘     └─────────────────┘     └─────────────────┘
     │                        │                        │
     │ 设计表单              │ 配置节点表单           │ 保存定义
     │ JSON Schema           │ 配置数据映射           │ - 表单定义
     │ UI Schema             │ 配置权限               │ - 流程定义
     ▼                       ▼                        ▼

2. 流程运行阶段
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   流程发起      │     │   节点激活      │     │   表单实例化    │
│  Start Flow     │ ──> │ Node Activated  │ ──> │ Form Instance   │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                                │                        │
                                │ 触发监听器             │ 创建表单实例
                                │                        │ 初始化数据
                                ▼                        ▼

3. 表单处理阶段
┌─────────────<E29480><E29480>───┐     ┌─────────────────┐     ┌─────────────────┐
│   表单渲染      │     │   表单交互      │     │   数据处理      │
│  Form Render    │ ──> │ Form Interact   │ ──> │ Data Process    │
└─────────────────┘     └─────────────────┘     └─────────────────┘
     │                        │                        │
     │ 加载表单定义          │ 用户输入               │ 数据验证
     │ 加载实例数据          │ 数据提交               │ 数据转换
     │ 应用权限              │                        │ 变量映射
     ▼                       ▼                        ▼

4. 节点完成阶段
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   表单提交      │     │   节点完成      │     │   流程推进      │
│  Form Submit    │ ──> │ Node Complete   │ ──> │ Flow Progress   │
└─────────────────┘     └─────────────<E29480><E29480><EFBFBD>───┘     └─────────────────┘
                                │                        │
                                │ 触发监听器             │ 流转到下一节点
                                │ 更新流程变量           │
                                ▼                        ▼

1.2 数据模型设计

  1. 表单定义(FormDefinition)
@Data
@Table(name = "workflow_form_definition")
@Entity
@LogicDelete
public class FormDefinition extends Entity<Long> {
    @Column(nullable = false)
    private String name;  // 表单名称
    
    @Column(nullable = false, unique = true)
    private String code;  // 表单编码
    
    @Column(columnDefinition = "TEXT")
    private String description;  // 表单描述
    
    @Type(JsonType.class)
    @Column(columnDefinition = "json", nullable = false)
    private JsonNode schema;  // 表单JSON Schema
    
    @Type(JsonType.class)
    @Column(columnDefinition = "json")
    private JsonNode uiSchema;  // UI渲染Schema
    
    @Column(nullable = false)
    private Boolean enabled = true;  // 是否启用
    
    @Column(nullable = false)
    private Integer version = 1;  // 版本号
}
  1. 表单实例(FormInstance)
@Data
@Table(name = "workflow_form_instance")
@Entity
@LogicDelete
public class FormInstance extends Entity<Long> {
    @Column(nullable = false)
    private Long formDefinitionId;  // 表单定义ID
    
    @Column(nullable = false)
    private String processInstanceId;  // 流程实例ID
    
    @Column(nullable = false)
    private String taskId;  // 任务ID
    
    @Type(JsonType.class)
    @Column(columnDefinition = "json", nullable = false)
    private JsonNode formData;  // 表单数据
    
    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private FormInstanceStatus status;  // 状态
}

2. 节点表单集成

2.1 工作流上下文设计

@Data
public class WorkflowContext {
    // 系统上下文
    private SystemContext systemContext;
    // 表单上下文
    private FormContext formContext;
    // 流程变量上下文
    private ProcessContext processContext;
    
    @Data
    public static class SystemContext {
        private JsonNode systemConfig;  // 系统配置
        private String executionId;     // 执行ID
        private String processInstanceId; // 流程实例ID
        private String nodeId;          // 节点ID
    }
    
    @Data
    public static class FormContext {
        private Long formInstanceId;    // 表单实例ID
        private JsonNode formData;      // 表单数据
        private JsonNode formConfig;    // 表单配置
        private Map<String, Object> mappedData; // 映射后的数据
    }
    
    @Data
    public static class ProcessContext {
        private Map<String, Object> variables;     // 流程变量
        private Map<String, Object> localVariables; // 节点本地变量
    }
}

2.2 节点定义中的表单配置

@Data
@Table(name = "workflow_node_definition")
@Entity
@LogicDelete
public class WorkflowNodeDefinition extends Entity<Long> {
    // ... 现有字段 ...

    /**
     * 表单配置
     */
    @Type(JsonType.class)
    @Column(columnDefinition = "json")
    private JsonNode formConfig;  // 节点默认的表单配置

    /**
     * 表单Schema
     */
    @Type(JsonType.class)
    @Column(columnDefinition = "json")
    private JsonNode formSchema;  // 节点默认的表单结构

    /**
     * 表单UI Schema
     */
    @Type(JsonType.class)
    @Column(columnDefinition = "json")
    private JsonNode formUiSchema;  // 节点默认的UI渲染配置
}

3. 动态接口支持

3.1 表单配置中的接口定义

{
    "formSchema": {
        "type": "object",
        "properties": {
            "department": {
                "type": "string",
                "title": "部门",
                "enum": "@api:getDepartments",
                "enumNames": "@api:getDepartmentNames"
            },
            "employee": {
                "type": "string",
                "title": "员工",
                "enum": "@api:getEmployeesByDepartment(department)",
                "enumNames": "@api:getEmployeeNamesByDepartment(department)"
            }
        }
    }
}

3.2 动态接口注册

@Service
public class DynamicApiRegistry {
    private final Map<String, DynamicApi> apiRegistry = new ConcurrentHashMap<>();
    
    @PostConstruct
    public void init() {
        // 注册系统内置API
        registerSystemApis();
    }
    
    // 注册API
    public void register(String apiKey, DynamicApi api) {
        apiRegistry.put(apiKey, api);
    }
    
    // 获取API
    public DynamicApi getApi(String apiKey) {
        return apiRegistry.get(apiKey);
    }
}

3.3 动态API定义

@Data
@Builder
public class DynamicApi {
    private String url;                     // API地址
    private HttpMethod method;              // 请求方法
    private Function<Map<String, Object>, Map<String, Object>> paramsBuilder;  // 参数构建器
    private String transform;               // 数据转换路径
    private Map<String, String> mapping;    // 数据映射
    private List<String> dependencies;      // 依赖字段
}

4. 使用示例

4.1 定义节点表单

{
    "systemConfig": {
        "timeout": 3600,
        "retryTimes": 3,
        "notifyEmail": "admin@example.com"
    },
    "formConfig": {
        "formSchema": { /* 表单结构 */ },
        "formUiSchema": { /* UI渲染配置 */ },
        "permissions": { /* 权限配置 */ },
        "dataMapping": {
            "input": { /* 输入映射 */ },
            "output": { /* 输出映射 */ }
        }
    }
}

4.2 注册动态接口

@Component
public class CustomApiConfig {
    
    @Resource
    private DynamicApiRegistry apiRegistry;
    
    @PostConstruct
    public void init() {
        // 注册项目查询API
        apiRegistry.register("getProjects", new DynamicApi.builder()
            .url("/api/v1/projects")
            .method(HttpMethod.GET)
            .paramsBuilder(context -> Map.of(
                "departmentId", context.get("department"),
                "employeeId", context.get("employee")
            ))
            .transform("data.list")
            .mapping(Map.of("value", "id", "label", "name"))
            .dependencies(List.of("department", "employee"))
            .build()
        );
    }
}

4.3 实现委派类

@Component
@Slf4j
public class ApprovalTaskDelegate extends BaseWorkflowDelegate {
    
    @Override
    protected void doExecute(WorkflowContext context) throws Exception {
        // 1. 获取表单数据
        FormContext formContext = context.getFormContext();
        Map<String, Object> mappedData = formContext.getMappedData();
        
        String approvalResult = (String) mappedData.get("approvalResult");
        String comments = (String) mappedData.get("comments");
        
        // 2. 获取系统配置
        SystemContext systemContext = context.getSystemContext();
        JsonNode systemConfig = systemContext.getSystemConfig();
        String notifyEmail = systemConfig.get("notifyEmail").asText();
        
        // 3. 处理审批结果
        ProcessContext processContext = context.getProcessContext();
        processContext.getVariables().put("approved", "APPROVED".equals(approvalResult));
        processContext.getVariables().put("approvalComments", comments);
        
        // 4. 发送通知
        if (notifyEmail != null) {
            notificationService.sendApprovalNotification(notifyEmail, approvalResult, comments);
        }
    }
}