BPMAXBPMAX
  • 快速入门
  • 核心概念
  • 管理员手册
  • 仿真和回放
  • 流程相关脚本
  • 表单相关脚本
  • 数据集相关脚本
  • 界面相关脚本
  • 系统相关脚本
  • 流程集成
  • 数据集
  • 接口集成
  • 实体映射
  • OpenAPI
  • 实体列表
  • 插件开发
  • 日志排查
  • 飞书平台

    • 同步组织架构
    • 同步团队组织架构
    • 一键拉群
    • 高级卡片消息
    • 服务台能力
  • 实用功能

    • 系统公告
    • 项目日历
    • 超时自动化
    • 报告自动生成
    • 流程资源档案
  • 文档更新记录
  • 系统更新说明
  • 快速入门
  • 核心概念
  • 管理员手册
  • 仿真和回放
  • 流程相关脚本
  • 表单相关脚本
  • 数据集相关脚本
  • 界面相关脚本
  • 系统相关脚本
  • 流程集成
  • 数据集
  • 接口集成
  • 实体映射
  • OpenAPI
  • 实体列表
  • 插件开发
  • 日志排查
  • 飞书平台

    • 同步组织架构
    • 同步团队组织架构
    • 一键拉群
    • 高级卡片消息
    • 服务台能力
  • 实用功能

    • 系统公告
    • 项目日历
    • 超时自动化
    • 报告自动生成
    • 流程资源档案
  • 文档更新记录
  • 系统更新说明
  • 插件开发入门

    • 插件开发
    • 插件架构与加载机制
    • 环境准备与开发模式
    • 第一个最小插件
  • 插件能力开发

    • 前端扩展点实战
    • 后端扩展点实战
    • 前后端联动完整案例:任务集成插件
  • 插件运行机制

    • 配置、安装、升级与发布
    • 定时任务与异步处理
    • Hook 机制与平台事件接入
    • 外部系统集成模式
  • 进阶与参考

    • 调试与排错
    • 设计规范与最佳实践
    • 能力类型索引与选型

前后端联动完整案例:任务集成插件

本文使用“任务集成插件”作为完整案例,串起 BPMAX 插件开发中最常见的一条业务链路:前端配置录入、后端逻辑执行、第三方接口调用。

学习目标

  • 用一个真实案例理解插件的完整开发路径
  • 学会从业务目标倒推前后端设计
  • 学会组织流程配置、接口调用和错误处理

业务背景

插件解决什么问题

任务集成插件的核心目标,是让 BPMAX 流程环节与外部任务能力联动。典型场景是:

  • 在某个流程环节启用外部任务创建
  • 根据流程上下文生成任务内容
  • 在适当时机更新或完成对应任务

为什么适合作为教学案例

这个插件的复杂度适中,具备一个完整业务插件常见的三个要素:

  • 前端环节配置
  • 后端第三方服务封装
  • 明确的业务字段结构

它比“纯页面插件”更真实,但又没有复杂到必须先理解 Kafka 或大规模异步任务。

先看整体设计

前端负责什么

前端入口文件做的事情非常集中:

  • 注册一个流程环节配置组件
  • 定义配置字段名
  • 提供默认值结构

代码核心如下:

import TaskStepConfig from './TaskStepConfig.vue';

BPMAX.flow.stepComponent({
  field: 'plugin_task_integration',
  component: TaskStepConfig,
  defaultValue: {
    enabled: false,
    mapping_function: '',
    platform_id: '',
  },
});

后端负责什么

后端服务层负责:

  • 获取第三方访问令牌
  • 创建外部任务
  • 完成外部任务

也就是说,前端只采集配置,真正的三方调用全部放在后端。

插件配置数据如何流转

这一类插件建议遵循以下链路:

  1. 前端配置组件采集参数
  2. 配置写入流程或环节配置数据
  3. 后端在执行节点读取配置
  4. 服务层把配置转成第三方接口参数
  5. 调用第三方接口并处理结果

前端实现

注册流程环节配置组件

任务集成类插件使用 BPMAX.flow.stepComponent,这说明它的配置是“环节级”的,而不是整个流程统一配置一次。

原因是:

  • 不是每个环节都要创建外部任务
  • 每个环节的任务映射规则可能不同

配置项字段设计

当前默认字段包括:

  • enabled
  • mapping_function
  • platform_id

这类结构的优点是很清晰:

  • enabled:决定是否启用
  • mapping_function:决定映射逻辑
  • platform_id:决定使用哪个平台实例

一个最小的环节配置组件可以先写成:

<script setup lang="ts">
const model = defineModel<any>({
  default: {
    enabled: false,
    mapping_function: '',
    platform_id: '',
  },
});
</script>

<template>
  <div class="task-step-config">
    <label>
      <span>启用任务集成</span>
      <input v-model="model.enabled" type="checkbox" />
    </label>

    <label>
      <span>平台实例</span>
      <input v-model="model.platform_id" type="text" placeholder="platform_a" />
    </label>

    <label>
      <span>映射函数</span>
      <input
        v-model="model.mapping_function"
        type="text"
        placeholder="buildTaskPayload"
      />
    </label>
  </div>
</template>

默认值与表单结构

这一类插件不要只用字符串存配置,建议一开始就把结构设计成对象,便于:

  • 后续加字段
  • 与历史版本兼容
  • 做前端校验

后端实现

插件服务封装

任务集成类插件的服务层本质上是一个第三方能力封装层。它没有把 HTTP 逻辑散落在控制器中,而是统一放在服务层。

这样做的好处是:

  • 控制器更轻
  • 逻辑更易复用
  • 便于单独调试第三方调用

控制器可以只保留参数接收和调用转发:

import BaseRest from '../rest.js';

@think.RestController()
export default class extends BaseRest {
  async createTaskAction() {
    const payload = this.post();
    const result = await this.service('plugin_task_integration').createTask(payload);
    return this.success(result);
  }
}

外部任务创建接口

服务层中有一个明确的方法:

async createExternalTask(platformConfig, payload) {
  const accessToken = await this.getAccessToken(
    platformConfig.app_id,
    platformConfig.secret
  );
  const res = await this.httpClient.post('/tasks', payload, {
    headers: {
      Authorization: 'Bearer ' + accessToken,
      'Content-Type': 'application/json; charset=utf-8',
    },
  });
  return res;
}

这里体现了一个值得复用的模式:

  1. 先解析平台配置
  2. 获取第三方 token
  3. 再调用业务接口

如果需要在创建前做字段映射,可以单独拆一个方法:

buildTaskPayload(project, config) {
  return {
    title: project.name,
    description: `来自流程 ${project.flow_name} 的任务`,
    owner: config.owner_id,
    source_id: project.guid,
  };
}

外部任务完成接口

插件还提供了任务完成能力:

async completeExternalTask(platformConfig, taskId) {
  const accessToken = await this.getAccessToken(
    platformConfig.app_id,
    platformConfig.secret
  );
  const res = await this.httpClient.patch(
    '/tasks/' + taskId,
    {
      status: 'completed',
      completed_at: Date.now(),
    },
    {
      headers: {
        Authorization: 'Bearer ' + accessToken,
        'Content-Type': 'application/json; charset=utf-8',
      },
    }
  );
  return res;
}

这说明插件不仅能“创建任务”,还应该考虑后续状态同步。对集成类插件来说,这一点很重要。

配置与运行

平台参数准备

运行这类插件前,通常至少要准备:

  • 第三方平台 app_id
  • 第三方平台 secret
  • 业务侧对应的平台实例配置

调试顺序建议

建议按这个顺序调试:

  1. 先确认前端配置组件是否显示
  2. 再确认配置数据是否正确保存
  3. 再确认后端是否能拿到平台配置
  4. 最后确认第三方接口调用是否成功

成功与失败的判断方式

不要只看页面有没有报错。至少要同时确认:

  • 前端配置是否已生效
  • 后端是否真正发出请求
  • 第三方是否返回成功
  • 返回结果是否被后续流程正确使用

从这个案例中抽象出的设计方法

前端只负责采集与展示

前端组件尽量只负责:

  • 显示配置项
  • 收集用户输入
  • 维护默认结构

后端负责调用与容错

所有三方调用、鉴权、错误处理都应尽量在后端完成,避免:

  • 泄露密钥
  • 把集成逻辑分散在页面里

第三方适配应封装在独立服务中

不要把第三方接口调用直接散落在控制器中。每种外部能力都应该有稳定的服务封装层。

可进一步扩展的方向

增加状态回写

例如 BPMAX 状态变化后自动回写外部任务状态。

增加重试与幂等

第三方任务创建失败时,可以考虑:

  • 重试策略
  • 幂等标识
  • 人工补偿

增加日志与监控

集成类插件如果没有日志,出问题时几乎无法定位。至少建议记录:

  • 平台实例
  • 请求接口
  • 核心参数摘要
  • 返回结果

下一步

  • 配置、安装、升级与发布
  • 外部系统集成模式
Prev
后端扩展点实战