deploy-ease-platform/backend/docs/frontend-guide.md
2024-12-05 15:25:08 +08:00

23 KiB
Raw Blame History

工作流前端对接文档

一、系统架构

1.1 整体架构

// 系统分层
interface SystemArchitecture {
    presentation: {
        views: '页面组件',      // 负责页面展示和用户交互
        components: '通用组件',  // 可复用的UI组件
        hooks: '业务钩子',      // 封装业务逻辑的Hooks
    };
    domain: {
        models: '数据模型',     // 核心业务模型定义
        services: '领域服务',   // 业务逻辑封装
        stores: '状态管理',     // 全局状态管理
    };
    infrastructure: {
        api: 'API封装',        // 后端接口调用
        utils: '工具函数',      // 通用工具方法
        constants: '常量定义',  // 系统常量
    };
}

1.2 核心模块

  1. 工作流设计器

    • 负责工作流的可视化设计
    • 节点拖拽和连线
    • 属性配置面板
    • 数据验证和保存
  2. 表单设计器

    • 工作流表单的可视化设计
    • 字段配置和验证规则
    • 布局设计
    • 表单预览
  3. 工作流引擎

    • 工作流实例管理
    • 节点状态控制
    • 变量管理
    • 日志记录

二、数据模型

2.1 工作流定义

interface WorkflowDefinition {
    // 基本信息
    id: number;                 // 工作流定义ID
    code: string;              // 工作流编码(唯一标识)
    name: string;              // 工作流名称
    description: string;       // 工作流描述
    version: number;           // 版本号
    status: WorkflowStatus;    // 状态DRAFT/PUBLISHED/DISABLED
    enabled: boolean;          // 是否启用

    // 节点定义
    nodes: Array<{
        id: number;            // 节点定义ID
        nodeId: string;        // 节点标识(在图中的唯一标识)
        name: string;          // 节点名称
        type: NodeType;        // 节点类型START/END/TASK/GATEWAY
        config: string;        // 节点配置JSON字符串
        description: string;   // 节点描述
        orderNum: number;      // 排序号
    }>;

    // 配置数据
    nodeConfig: string;        // 节点关系配置JSON字符串
    transitionConfig: string;  // 流转配置JSON字符串
    formDefinition: string;    // 表单定义JSON字符串
    graphDefinition: string;   // 图形布局JSON字符串
}

// 节点配置示例JSON格式
interface NodeConfig {
    // 开始节点配置
    startNode: {
        type: 'START';
        name: string;
        config?: Record<string, any>;
    };

    // 任务节点配置
    taskNodes: Array<{
        id: string;
        type: 'TASK';
        name: string;
        executor?: string;         // 执行器类型
        config: {
            // Shell执行器配置
            script?: string;       // 脚本内容
            timeout?: number;      // 超时时间
            workingDir?: string;   // 工作目录
            
            // Jenkins执行器配置
            jenkinsJob?: string;   // Jenkins任务名
            parameters?: Record<string, any>; // 构建参数
        };
    }>;

    // 网关节点配置
    gatewayNodes: Array<{
        id: string;
        type: 'GATEWAY';
        name: string;
        gatewayType: 'EXCLUSIVE' | 'PARALLEL' | 'INCLUSIVE'; // 网关类型
        conditions?: Array<{
            expression: string;    // 条件表达式
            description: string;   // 条件描述
        }>;
    }>;

    // 结束节点配置
    endNode: {
        type: 'END';
        name: string;
        config?: Record<string, any>;
    };
}

// 流转配置示例
interface TransitionConfig {
    transitions: Array<{
        from: string;          // 源节点ID
        to: string;            // 目标节点ID
        condition?: string;    // 流转条件(网关节点使用)
        priority?: number;     // 优先级(条件分支使用)
    }>;
}

// 图形布局示例
interface GraphDefinition {
    nodes: Array<{
        id: string;           // 节点ID
        type: string;         // 节点类型
        x: number;           // X坐标
        y: number;           // Y坐标
        properties?: {       // 节点属性
            width?: number;
            height?: number;
            color?: string;
            icon?: string;
        };
    }>;
    edges: Array<{
        source: string;      // 源节点ID
        target: string;      // 目标节点ID
        points?: Array<{    // 连线控制点
            x: number;
            y: number;
        }>;
        properties?: {      // 连线属性
            style?: string;
            arrow?: string;
            label?: string;
        };
    }>;
}

2.2 工作流实例

interface WorkflowInstance {
    id: number;                // 实例ID
    definitionId: number;      // 工作流定义ID
    businessKey: string;       // 业务标识
    status: InstanceStatus;    // 状态
    startTime: string;         // 开始时间
    endTime: string;          // 结束时间
    variables: string;        // 工作流变量JSON字符串
    error: string;           // 错误信息
}

interface NodeInstance {
    id: number;              // 实例ID
    workflowInstanceId: number; // 工作流实例ID
    nodeId: string;          // 节点ID
    nodeType: NodeType;      // 节点类型
    status: NodeStatus;      // 节点状态
    startTime: string;       // 开始时间
    endTime: string;         // 结束时间
    input: string;           // 输入参数JSON字符串
    output: string;          // 输出结果JSON字符串
    error: string;           // 错误信息
}

三、接口定义

3.1 工作流定义接口

interface WorkflowDefinitionAPI {
    // 基础CRUD
    create: {
        url: '/api/v1/workflow-definitions',
        method: 'POST',
        data: WorkflowDefinitionDTO,
        response: Response<WorkflowDefinitionDTO>
    };
    
    update: {
        url: '/api/v1/workflow-definitions/{id}',
        method: 'PUT',
        data: WorkflowDefinitionDTO,
        response: Response<WorkflowDefinitionDTO>
    };
    
    delete: {
        url: '/api/v1/workflow-definitions/{id}',
        method: 'DELETE',
        response: Response<void>
    };
    
    getById: {
        url: '/api/v1/workflow-definitions/{id}',
        method: 'GET',
        response: Response<WorkflowDefinitionDTO>
    };
    
    page: {
        url: '/api/v1/workflow-definitions/page',
        method: 'GET',
        params: PageQuery,
        response: Response<Page<WorkflowDefinitionDTO>>
    };

    // 特殊操作
    publish: {
        url: '/api/v1/workflow-definitions/{id}/publish',
        method: 'POST',
        response: Response<WorkflowDefinitionDTO>
    };
    
    disable: {
        url: '/api/v1/workflow-definitions/{id}/disable',
        method: 'POST',
        response: Response<WorkflowDefinitionDTO>
    };
    
    enable: {
        url: '/api/v1/workflow-definitions/{id}/enable',
        method: 'POST',
        response: Response<WorkflowDefinitionDTO>
    };
}

3.2 工作流实例接口

interface WorkflowInstanceAPI {
    // 实例操作
    start: {
        url: '/api/v1/workflow-instances/start',
        method: 'POST',
        data: {
            workflowCode: string;    // 工作流编码
            businessKey: string;     // 业务标识
            variables?: Record<string, any>; // 工作流变量
        },
        response: Response<WorkflowInstanceDTO>
    };
    
    terminate: {
        url: '/api/v1/workflow-instances/{id}/terminate',
        method: 'POST',
        data: {
            reason?: string;        // 终止原因
        },
        response: Response<void>
    };
    
    pause: {
        url: '/api/v1/workflow-instances/{id}/pause',
        method: 'POST',
        response: Response<void>
    };
    
    resume: {
        url: '/api/v1/workflow-instances/{id}/resume',
        method: 'POST',
        response: Response<void>
    };

    // 查询接口
    getById: {
        url: '/api/v1/workflow-instances/{id}',
        method: 'GET',
        response: Response<WorkflowInstanceDTO>
    };
    
    page: {
        url: '/api/v1/workflow-instances/page',
        method: 'GET',
        params: PageQuery & {
            status?: InstanceStatus;
            startTime?: string;
            endTime?: string;
            keyword?: string;
        },
        response: Response<Page<WorkflowInstanceDTO>>
    };
}

四、组件设计

4.1 工作流设计器

// 1. 设计器组件
interface WorkflowDesigner {
    // 属性定义
    props: {
        value?: WorkflowDefinition;   // 工作流定义数据
        readOnly?: boolean;           // 是否只读
        onChange?: (value: WorkflowDefinition) => void; // 数据变更回调
    };
    
    // 子组件
    components: {
        ToolBar: '工具栏',           // 撤销、重做、缩放等操作
        NodePanel: '节点面板',       // 可用节点列表
        Canvas: '画布',              // 节点拖拽和连线
        ConfigPanel: '配置面板',     // 节点和连线配置
        MiniMap: '小地图'           // 导航缩略图
    };
    
    // 核心方法
    methods: {
        // 初始化设计器
        initialize(definition: WorkflowDefinition): void;
        
        // 添加节点
        addNode(nodeData: NodeData): void;
        
        // 连接节点
        connect(source: string, target: string): void;
        
        // 更新节点配置
        updateNodeConfig(nodeId: string, config: any): void;
        
        // 更新连线配置
        updateEdgeConfig(edgeId: string, config: any): void;
        
        // 验证数据
        validate(): ValidationResult;
        
        // 导出数据
        exportData(): WorkflowDefinition;
    };
}

// 2. 节点配置面板
interface NodeConfigPanel {
    props: {
        node: NodeData;              // 节点数据
        nodeType: NodeType;          // 节点类型
        onChange: (config: any) => void; // 配置变更回调
    };
    
    // 配置表单定义
    forms: {
        // 基础配置(所有节点都有)
        BaseConfig: {
            name: string;           // 节点名称
            description?: string;   // 节点描述
        };
        
        // 任务节点配置
        TaskConfig: {
            executor: string;       // 执行器类型
            config: Record<string, any>; // 执行器配置
        };
        
        // 网关节点配置
        GatewayConfig: {
            type: 'EXCLUSIVE' | 'PARALLEL' | 'INCLUSIVE';
            conditions?: Array<{
                expression: string;
                description: string;
            }>;
        };
    };
}

// 3. 连线配置面板
interface EdgeConfigPanel {
    props: {
        edge: EdgeData;             // 连线数据
        sourceNode: NodeData;       // 源节点
        targetNode: NodeData;       // 目标节点
        onChange: (config: any) => void; // 配置变更回调
    };
    
    // 配置表单定义
    forms: {
        condition?: string;         // 流转条件
        priority?: number;          // 优先级
        description?: string;       // 说明
    };
}

4.2 表单设计器

interface FormDesigner {
    props: {
        value?: FormDefinition;    // 表单定义数据
        onChange?: (value: FormDefinition) => void; // 数据变更回调
    };
    
    // 可用的字段类型
    fieldTypes: {
        input: '单行文本',
        textarea: '多行文本',
        number: '数字',
        select: '下拉选择',
        radio: '单选',
        checkbox: '多选',
        date: '日期',
        datetime: '日期时间',
        file: '文件上传'
    };
    
    // 字段属性定义
    fieldProperties: {
        name: string;              // 字段名
        label: string;             // 字段标签
        type: string;              // 字段类型
        required?: boolean;        // 是否必填
        defaultValue?: any;        // 默认值
        placeholder?: string;      // 占位提示
        description?: string;      // 字段描述
        options?: Array<{         // 选项用于select/radio/checkbox
            label: string;
            value: any;
        }>;
        validation?: Array<{      // 验证规则
            type: string;         // 规则类型
            message: string;      // 错误消息
            params?: any;        // 规则参数
        }>;
    };
}

五、状态管理

5.1 工作流设计器状态

interface DesignerState {
    // 画布状态
    canvas: {
        scale: number;            // 缩放比例
        position: {               // 画布位置
            x: number;
            y: number;
        };
        selectedElements: {       // 选中的元素
            nodes: string[];      // 节点ID列表
            edges: string[];      // 连线ID列表
        };
    };
    
    // 历史记录
    history: {
        undoStack: HistoryItem[]; // 撤销栈
        redoStack: HistoryItem[]; // 重做栈
        canUndo: boolean;         // 是否可撤销
        canRedo: boolean;         // 是否可重做
    };
    
    // 节点数据
    nodes: Record<string, NodeData>;  // 节点数据映射
    edges: Record<string, EdgeData>;  // 连线数据映射
    
    // 配置面板
    configPanel: {
        visible: boolean;         // 是否显示
        type: 'node' | 'edge';    // 配置类型
        elementId?: string;       // 当前配置的元素ID
    };
}

5.2 工作流实例状态

interface InstanceState {
    // 实例数据
    instance: {
        current?: WorkflowInstance;  // 当前实例
        nodes: NodeInstance[];       // 节点实例列表
        variables: Record<string, any>; // 工作流变量
    };
    
    // 操作权限
    permissions: {
        canTerminate: boolean;      // 是否可终止
        canPause: boolean;          // 是否可暂停
        canResume: boolean;         // 是否可恢复
    };
    
    // 日志数据
    logs: {
        workflow: WorkflowLog[];    // 工作流日志
        nodes: Record<string, NodeLog[]>; // 节点日志
    };
}

六、工作流设计器使用示例

6.1 基础使用

// 1. 创建工作流
const createWorkflow = async (definition: WorkflowDefinition) => {
    try {
        // 验证数据
        const validationResult = workflowDesigner.validate();
        if (!validationResult.valid) {
            message.error('工作流数据验证失败:' + validationResult.errors.join(', '));
            return;
        }
        
        // 提交数据
        const response = await WorkflowDefinitionAPI.create(definition);
        if (response.code === 200) {
            message.success('工作流创建成功');
            return response.data;
        } else {
            message.error('工作流创建失败:' + response.message);
        }
    } catch (error) {
        message.error('系统错误:' + error.message);
    }
};

// 2. 加载工作流
const loadWorkflow = async (id: number) => {
    try {
        const response = await WorkflowDefinitionAPI.getById(id);
        if (response.code === 200) {
            // 初始化设计器
            workflowDesigner.initialize(response.data);
            return response.data;
        } else {
            message.error('加载工作流失败:' + response.message);
        }
    } catch (error) {
        message.error('系统错误:' + error.message);
    }
};

// 3. 保存工作流
const saveWorkflow = async (id: number) => {
    try {
        // 获取设计器数据
        const definition = workflowDesigner.exportData();
        
        // 验证数据
        const validationResult = workflowDesigner.validate();
        if (!validationResult.valid) {
            message.error('工作流数据验证失败:' + validationResult.errors.join(', '));
            return;
        }
        
        // 提交数据
        const response = await WorkflowDefinitionAPI.update(id, definition);
        if (response.code === 200) {
            message.success('工作流保存成功');
            return response.data;
        } else {
            message.error('工作流保存失败:' + response.message);
        }
    } catch (error) {
        message.error('系统错误:' + error.message);
    }
};

6.2 节点配置示例

// 1. Shell节点配置
const ShellNodeConfig = {
    type: 'TASK',
    name: 'Shell脚本',
    executor: 'SHELL',
    config: {
        script: '#!/bin/bash\necho "Hello World"',
        timeout: 300,
        workingDir: '/tmp'
    }
};

// 2. Jenkins节点配置
const JenkinsNodeConfig = {
    type: 'TASK',
    name: 'Jenkins构建',
    executor: 'JENKINS',
    config: {
        jenkinsJob: 'my-project-build',
        parameters: {
            BRANCH: 'master',
            ENV: 'prod'
        }
    }
};

// 3. 网关节点配置
const GatewayNodeConfig = {
    type: 'GATEWAY',
    name: '条件分支',
    gatewayType: 'EXCLUSIVE',
    conditions: [
        {
            expression: '${status} == "SUCCESS"',
            description: '执行成功'
        },
        {
            expression: '${status} == "FAILED"',
            description: '执行失败'
        }
    ]
};

6.3 数据验证示例

// 1. 节点配置验证
const validateNodeConfig = (node: NodeData): ValidationResult => {
    const errors: string[] = [];
    
    // 基础验证
    if (!node.name) {
        errors.push('节点名称不能为空');
    }
    
    // 任务节点特殊验证
    if (node.type === 'TASK') {
        if (!node.executor) {
            errors.push('请选择执行器');
        }
        
        // Shell执行器验证
        if (node.executor === 'SHELL') {
            if (!node.config.script) {
                errors.push('脚本内容不能为空');
            }
        }
        
        // Jenkins执行器验证
        if (node.executor === 'JENKINS') {
            if (!node.config.jenkinsJob) {
                errors.push('Jenkins任务名不能为空');
            }
        }
    }
    
    // 网关节点特殊验证
    if (node.type === 'GATEWAY') {
        if (!node.gatewayType) {
            errors.push('请选择网关类型');
        }
        if (node.gatewayType === 'EXCLUSIVE' && (!node.conditions || node.conditions.length === 0)) {
            errors.push('请配置分支条件');
        }
    }
    
    return {
        valid: errors.length === 0,
        errors
    };
};

// 2. 流程验证
const validateWorkflow = (definition: WorkflowDefinition): ValidationResult => {
    const errors: string[] = [];
    
    // 1. 基础信息验证
    if (!definition.name) {
        errors.push('工作流名称不能为空');
    }
    if (!definition.code) {
        errors.push('工作流编码不能为空');
    }
    
    // 2. 节点验证
    const nodes = JSON.parse(definition.nodeConfig);
    
    // 验证开始节点
    if (!nodes.startNode) {
        errors.push('必须有一个开始节点');
    }
    
    // 验证结束节点
    if (!nodes.endNode) {
        errors.push('必须有一个结束节点');
    }
    
    // 验证任务节点
    if (!nodes.taskNodes || nodes.taskNodes.length === 0) {
        errors.push('至少需要一个任务节点');
    }
    
    // 3. 连线验证
    const transitions = JSON.parse(definition.transitionConfig).transitions;
    
    // 验证是否有孤立节点
    const connectedNodes = new Set<string>();
    transitions.forEach(t => {
        connectedNodes.add(t.from);
        connectedNodes.add(t.to);
    });
    
    const allNodes = [
        nodes.startNode,
        ...nodes.taskNodes,
        ...(nodes.gatewayNodes || []),
        nodes.endNode
    ];
    
    allNodes.forEach(node => {
        if (!connectedNodes.has(node.id)) {
            errors.push(`节点 ${node.name}(${node.id}) 未连接`);
        }
    });
    
    // 4. 验证是否有环
    if (hasCircle(transitions)) {
        errors.push('流程中存在循环');
    }
    
    return {
        valid: errors.length === 0,
        errors
    };
};

七、最佳实践

7.1 性能优化

  1. 大数据量处理

    • 使用虚拟滚动
    • 分页加载数据
    • 按需渲染节点
  2. 状态管理

    • 合理使用缓存
    • 避免频繁更新
    • 使用不可变数据
  3. 渲染优化

    • 组件懒加载
    • 合理使用memo
    • 避免不必要的重渲染

7.2 错误处理

  1. 前端验证

    • 实时验证
    • 提供错误提示
    • 防止无效操作
  2. 异常捕获

    • 全局错误处理
    • 友好的错误提示
    • 错误日志记录
  3. 数据恢复

    • 自动保存
    • 本地缓存
    • 操作回滚

7.3 用户体验

  1. 交互设计

    • 拖拽操作流畅
    • 实时预览效果
    • 快捷键支持
  2. 反馈机制

    • 操作提示
    • 加载状态
    • 成功/失败反馈
  3. 辅助功能

    • 自动布局
    • 查找/替换
    • 导入/导出

八、常见问题

8.1 配置相关

  1. 节点配置问题

    • Q: 如何处理不同类型节点的配置?
    • A: 使用统一的配置接口,通过类型区分不同的配置表单
  2. 数据同步问题

    • Q: 如何保持前端展示数据与后端数据一致?
    • A: 实现定期自动保存和加载机制
  3. 验证问题

    • Q: 如何确保工作流数据的正确性?
    • A: 实现多层次的验证机制,包括实时验证和提交验证

8.2 性能相关

  1. 大型工作流

    • Q: 如何处理节点数量很多的工作流?
    • A: 实现分区渲染和虚拟滚动
  2. 频繁操作

    • Q: 如何处理频繁的拖拽和连线操作?
    • A: 使用节流和防抖优化性能
  3. 数据量大

    • Q: 如何处理大量的历史数据?
    • A: 实现分页加载和懒加载机制

九、开发规范

9.1 代码规范

  1. 命名规范

    • 组件使用大驼峰命名
    • 方法使用小驼峰命名
    • 常量使用大写下划线
  2. 注释规范

    • 组件必须有文档注释
    • 复杂逻辑需要注释
    • 保持注释的及时更新
  3. 类型规范

    • 使用TypeScript
    • 定义清晰的接口
    • 避免any类型

9.2 提交规范

  1. 提交信息

    • feat: 新功能
    • fix: 修复bug
    • docs: 文档更新
    • style: 代码格式
    • refactor: 重构
    • test: 测试
    • chore: 构建过程或辅助工具的变动
  2. 分支管理

    • master: 主分支
    • develop: 开发分支
    • feature: 功能分支
    • hotfix: 紧急修复分支

9.3 测试规范

  1. 单元测试

    • 组件测试
    • 方法测试
    • 工具函数测试
  2. 集成测试

    • 流程测试
    • 接口测试
    • 兼容性测试
  3. E2E测试

    • 用户操作测试
    • 场景测试
    • 性能测试