# bkflow-canvas-editor

bkflow流程编辑组件，支持流程的编辑、查看、调试以及创建并执行任务。

## 安装

```bash
npm install @blueking/bkflow-canvas-editor
```

## 使用

### 基础使用

```vue
<template>
  <FlowView
    :flow-id="flowId"
    :api-config="apiConfig"
    :permissions="{ canEdit: true }"
    @edit="handleEdit"
    @back="handleBack" />
</template>

<script setup>
  import { FlowView } from 'bkflow-canvas-editor';
  import 'bkflow-canvas-editor/style';
  import axios from 'axios';

  const flowId = '123';

  // 配置 API
  const apiConfig = {
    baseURL: window.API_HOST, // API 基础路径（可选，默认使用 window.API_HOST）
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    }, // 作用域数据（必需）
    fetchUserApi: `${window.BK_COMPONENT_API_URL}/api/c/compapi/v2/usermanage/fs_list_users/`, // 用户查询 API（可选）
    // 可选：使用自定义 axios 实例
    // axiosInstance: customAxiosInstance,
    // 可选：axios 配置
    // axiosConfig: {
    //   timeout: 10000,
    //   headers: { ... }
    // },
  };

  const handleEdit = () => {
    // 跳转到编辑页面
  };

  const handleBack = () => {
    // 返回处理
  };
</script>
```

## 组件 API

### FlowView 组件

流程查看组件，用于查看流程的详细信息。

#### Props

| 参数                | 类型                                             | 默认值              | 说明                                                                                                                        |
| ------------------- | ------------------------------------------------ | ------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `flowId`            | `string`                                         | -                   | **必需**，流程 ID                                                                                                           |
| `apiConfig`         | `FlowApiConfig`                                  | -                   | **必需**，API 配置对象，详见 [API 配置](#api-配置)                                                                          |
| `permissions`       | `{ canEdit?: boolean }`                          | `{ canEdit: true }` | 权限配置对象，`canEdit` 控制头部编辑按钮是否使用禁用样式                                                                    |
| `thumbnail`         | `boolean`                                        | `false`             | 小地图模式，启用后只显示画布内容，不显示顶部 header 和操作按钮，禁用节点点击事件                                            |
| `enableVersion`     | `boolean`                                        | `false`             | 是否开启流程版本功能，开启后会根据 `flowVersion` 的值获取对应版本的流程数据                                                 |
| `flowVersion`       | `string`                                         | -                   | 流程版本号，仅在 `enableVersion` 为 `true` 时生效。为空时表示草稿版本，不为空时表示指定版本                                 |
| `showHeaderActions` | `boolean`                                        | `true`              | 是否显示头部操作按钮（编辑、执行流程、调试），仅在非小地图模式下生效                                                        |
| `defaultZoom`       | `number`                                         | `1`                 | x6 画布的默认缩放比例，用于控制画布的初始显示效果。取值范围建议在 0.25 到 1.5 之间                                          |
| `bkflowSaasUrl`     | `string`                                         | -                   | bkflow-saas-url，用于设置 `$.context.site_url` 的值，供插件内部使用                                                         |
| `onEdit`            | `() => void`                                     | -                   | 编辑按钮点击回调（可选，也可以通过 `@edit` 事件监听）                                                                       |
| `onBack`            | `() => void`                                     | -                   | 返回按钮点击回调（可选，也可以通过 `@back` 事件监听）                                                                       |
| `onExecuteSuccess`  | `(result: FlowTaskExecuteSuccessResult) => void` | -                   | 执行成功回调（可选），参数含 `createResult`(create_task) 与 `executeResult`(operate_task)，用 `executeResult.data.url` 跳转 |

#### Slots

| 插槽名        | 作用域参数 | 说明                   |
| ------------- | ---------- | ---------------------- |
| `header`      | -          | 自定义头部内容         |
| `inputParams` | 见下方说明 | 自定义节点输入参数组件 |

##### inputParams 插槽作用域参数

| 参数                | 类型                                                  | 说明                                                   |
| ------------------- | ----------------------------------------------------- | ------------------------------------------------------ |
| `node`              | `Activity`                                            | 当前节点数据                                           |
| `pluginDetail`      | `PluginDetailCommon \| null`                          | 插件详情（统一类型，支持所有插件类型）                 |
| `inputs`            | `UniformApiPluginInputsItem[]`                        | 输入参数表单配置列表                                   |
| `editable`          | `boolean`                                             | 是否可编辑                                             |
| `fullVariableList`  | `{ key: string; name: string }[]`                     | 完整变量列表（系统变量 + 常量）                        |
| `updateInputParams` | `(data: Record<string, PluginInputDataItem>) => void` | 更新节点输入参数的方法（暂存，需点击确定按钮才会保存） |

#### Events

| 事件名 | 参数 | 说明               |
| ------ | ---- | ------------------ |
| `edit` | -    | 点击编辑按钮时触发 |
| `back` | -    | 点击返回按钮时触发 |

---

### FlowEdit 组件

流程编辑组件，用于编辑流程的配置和节点信息。

#### Props

| 参数                    | 类型                                                                                         | 默认值              | 说明                                                                                                                        |
| ----------------------- | -------------------------------------------------------------------------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `flowId`                | `string`                                                                                     | -                   | **必需**，流程 ID                                                                                                           |
| `apiConfig`             | `FlowApiConfig`                                                                              | -                   | **必需**，API 配置对象，详见 [API 配置](#api-配置)                                                                          |
| `permissions`           | `{ canSave?: boolean }`                                                                      | `{ canSave: true }` | 权限配置对象，`canSave` 控制头部保存按钮是否可点击                                                                          |
| `enableDebug`           | `boolean`                                                                                    | `false`             | 是否启用调试功能，启用后显示可点击的调试按钮                                                                                |
| `enableVersion`         | `boolean`                                                                                    | `false`             | 是否开启流程版本功能，开启后会根据 `flowVersion` 的值获取对应版本的流程数据                                                 |
| `flowVersion`           | `string`                                                                                     | -                   | 流程版本号，仅在 `enableVersion` 为 `true` 时生效。为空时表示草稿版本，不为空时表示指定版本                                 |
| `onDebugConfirm`        | `(formData: { name: string, variablesValue: Record<string, any> }) => Promise<void> \| void` | -                   | 调试面板确定按钮回调（可选）                                                                                                |
| `useCustomDebugConfirm` | `boolean`                                                                                    | `false`             | 是否使用自定义回调替代调试面板原有逻辑。为 `true` 时只执行 `onDebugConfirm`，为 `false` 时在原有逻辑后执行 `onDebugConfirm` |
| `selectPanelConfig`     | `SelectPanelConfig`                                                                          | -                   | 插件选择面板配置（可选），详见 [SelectPanelConfig](#selectpanelconfig)                                                      |
| `onSave`                | `(flowData: FlowTemplate) => void`                                                           | -                   | 保存回调（可选，也可以通过 `@save` 事件监听）                                                                               |
| `onSaveSuccess`         | `() => void`                                                                                 | -                   | 保存成功回调（可选，也可以通过 `@saveSuccess` 事件监听）                                                                    |
| `onBack`                | `() => void`                                                                                 | -                   | 返回按钮点击回调（可选，也可以通过 `@back` 事件监听）                                                                       |
| `onBeforeLeave`         | `(isEdited: boolean) => Promise<boolean>`                                                    | -                   | 离开前回调，返回 `false` 可阻止离开                                                                                         |
| `defaultZoom`           | `number`                                                                                     | `1`                 | x6 画布的默认缩放比例，用于控制画布的初始显示效果。取值范围建议在 0.25 到 1.5 之间                                          |
| `bkflowSaasUrl`         | `string`                                                                                     | -                   | bkflow-saas-url，用于设置 `$.context.site_url` 的值，供插件内部使用                                                         |
| `enableThirdPlugin`     | `boolean`                                                                                    | `true`              | 是否启用第三方插件。设置为 `false` 时，将不加载第三方插件列表和详情，只显示内置插件                                         |
| `quickAdd`              | `QuickAddConfig`                                                                             | -                   | 透传给底层画布的 quick-add 配置；默认启用，可自定义绑定端口、插入方向或显式关闭                                             |

#### Slots

| 插槽名                   | 作用域参数 | 说明                         |
| ------------------------ | ---------- | ---------------------------- |
| `header`                 | -          | 自定义头部内容               |
| `inputParams`            | 见下方说明 | 自定义节点输入参数组件       |
| `debugCustomFormContent` | 见下方说明 | 自定义调试组件的表单内容插槽 |

##### inputParams 插槽作用域参数

| 参数                    | 类型                                                         | 说明                                                                                     |
| ----------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
| `node`                  | `Activity`                                                   | 当前节点数据                                                                             |
| `pluginDetail`          | `PluginDetailCommon \| null`                                 | 插件详情（统一类型，支持所有插件类型）                                                   |
| `inputs`                | `UniformApiPluginInputsItem[]`                               | 输入参数表单配置列表                                                                     |
| `editable`              | `boolean`                                                    | 是否可编辑                                                                               |
| `fullVariableList`      | `{ key: string; name: string }[]`                            | 完整变量列表（系统变量 + 常量）                                                          |
| `updateInputParams`     | `(data: Record<string, PluginInputDataItem>) => void`        | 更新节点输入参数的方法（暂存到节点配置面板，需点击确定按钮才会保存）                     |
| `updateNodeInputParams` | `(inputParams: Record<string, PluginInputDataItem>) => void` | 更新节点输入参数的方法（通过 edit 组件调用，暂存到节点配置面板，需点击确定按钮才会保存） |

##### debugCustomFormContent 插槽作用域参数

| 参数             | 类型                  | 说明       |
| ---------------- | --------------------- | ---------- |
| `formData`       | `{ name: string }`    | 表单数据   |
| `variablesValue` | `Record<string, any>` | 变量值对象 |

#### Events

| 事件名             | 参数                     | 说明                             |
| ------------------ | ------------------------ | -------------------------------- |
| `save`             | `flowData: FlowTemplate` | 保存时触发，参数为流程数据       |
| `saveSuccess`      | -                        | 保存成功时触发                   |
| `back`             | -                        | 点击返回按钮时触发               |
| `debugBeforeClose` | -                        | 调试面板关闭前触发，用于清理数据 |

#### 暴露的方法

通过 `ref` 可以访问组件实例：

| 方法名                  | 参数                                               | 返回值                 | 说明                                                       |
| ----------------------- | -------------------------------------------------- | ---------------------- | ---------------------------------------------------------- |
| `updateNodeInputParams` | `inputParams: Record<string, PluginInputDataItem>` | `void`                 | 更新当前打开节点的输入参数（暂存，需点击确定按钮才会保存） |
| `isFlowEdited`          | -                                                  | `ComputedRef<boolean>` | 流程是否已编辑（只读）                                     |

---

### SelectPanelConfig 类型

插件选择面板配置类型，用于配置插件选择面板中的按钮跳转链接和文本。

#### 类型定义

```typescript
interface SelectPanelConfig {
  agentApplyUrl?: string; // 智能体插件分组，"点击申请" 按钮跳转链接（可选）
  agentResourceUrl?: string; // "智能体" 按钮跳转链接（可选）
  agentButtonText?: string; // "智能体" 按钮文本（可选，默认为 "智能体"）
  knowledgebaseResourceUrl?: string; // 知识库插件分组，"知识库" 按钮跳转链接（可选）
}
```

#### 使用示例

```vue
<template>
  <FlowEdit
    :flow-id="flowId"
    :api-config="apiConfig"
    :select-panel-config="{
      agentApplyUrl: 'https://example.com/apply',
      agentResourceUrl: 'https://example.com/agent',
      agentButtonText: '创建智能体',
      knowledgebaseResourceUrl: 'https://example.com/knowledgebase',
    }" />
</template>
```

#### 说明

- 如果 `selectPanelConfig` 未提供或某个字段未提供，组件将使用默认的路由跳转行为
- `agentButtonText` 默认值为 "智能体"
- 配置通过 Vue 的 provide/inject 机制全局提供，子组件可以直接通过 `useSelectPanelConfig()` 获取

---

### FlowCreateTask 组件

创建任务组件，用于填写参数并创建、触发执行流程任务。

#### Props

| 参数               | 类型                                             | 默认值  | 说明                                                                                                                |
| ------------------ | ------------------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------- |
| `flowId`           | `string`                                         | -       | **必需**，流程 ID                                                                                                   |
| `show`             | `boolean`                                        | -       | **必需**，是否显示执行面板                                                                                          |
| `apiConfig`        | `FlowApiConfig`                                  | -       | **必需**，API 配置对象，详见 [API 配置](#api-配置)                                                                  |
| `editable`         | `boolean`                                        | `true`  | 是否可编辑                                                                                                          |
| `showFlowEntry`    | `boolean`                                        | `false` | 是否显示流程入口                                                                                                    |
| `bkflowSaasUrl`    | `string`                                         | -       | bkflow-saas-url，用于设置 `$.context.site_url` 的值，供插件内部使用                                                 |
| `onExecuteSuccess` | `(result: FlowTaskExecuteSuccessResult) => void` | -       | 执行成功回调，参数含 `createResult`(create_task) 与 `executeResult`(operate_task)，用 `executeResult.data.url` 跳转 |

#### Events

| 事件名         | 参数                                   | 说明                     |
| -------------- | -------------------------------------- | ------------------------ |
| `confirm`      | `result: FlowTaskExecuteSuccessResult` | 执行确认时触发           |
| `close`        | -                                      | 关闭面板时触发           |
| `update:show`  | `show: boolean`                        | 显示状态更新时触发       |
| `before-close` | -                                      | 面板关闭前触发           |
| `view-flow`    | -                                      | 点击查看排障流程按钮触发 |

#### Slots

| 插槽名              | Slot Props                                                                                     | 说明                                                               |
| ------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `customFormContent` | `customFormData`、`additionalTaskParams`、`updateCustomFormData`、`updateAdditionalTaskParams` | 自定义额外表单项；`additionalTaskParams` 会合并进 `createFlowTask` |

---

### FlowExecute 组件

流程执行视图组件，在任务执行页面嵌入只读画布，内置节点和连线在不同执行状态（未执行、成功、失败、执行中）下的样式效果。

#### Props

| 参数            | 类型                  | 默认值 | 说明                                          |
| --------------- | --------------------- | ------ | --------------------------------------------- |
| `pipelineTree`  | `PipelineTree`        | -      | **必需**，任务使用的流程模板数据              |
| `nodeStates`    | `TaskExecutionStates` | `{}`   | 节点执行状态映射 `Record<nodeId, { status }>` |
| `defaultZoom`   | `number`              | `1`    | 默认缩放比例                                  |
| `apiConfig`     | `FlowApiConfig`       | -      | **必需**，API 配置对象                        |
| `bkflowSaasUrl` | `string`              | -      | bkflow SaaS 地址                              |
| `onBack`        | `() => void`          | -      | 返回回调                                      |

#### Events

| 事件名       | 参数            | 说明             |
| ------------ | --------------- | ---------------- |
| `back`       | -               | 点击返回按钮触发 |
| `node-click` | `CanvasUiEvent` | 点击节点时触发   |
| `ui-event`   | `CanvasUiEvent` | 画布交互事件透传 |

#### Slots

| 插槽名   | 说明               |
| -------- | ------------------ |
| `header` | 完全替换默认标题区 |
| `extend` | 标题栏右侧扩展区域 |

---

### FlowDebug 组件

流程调试组件，用于调试流程任务。基于 `FlowCreateTask` 组件实现，但增加了自定义表单插槽、自定义确定按钮回调及版本控制支持。

#### Props

| 参数               | 类型                                                                                         | 默认值  | 说明                                                                                                      |
| ------------------ | -------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `flowId`           | `string`                                                                                     | -       | **必需**，流程 ID                                                                                         |
| `show`             | `boolean`                                                                                    | -       | **必需**，是否显示调试面板                                                                                |
| `apiConfig`        | `FlowApiConfig`                                                                              | -       | **必需**，API 配置对象，详见 [API 配置](#api-配置)                                                        |
| `editable`         | `boolean`                                                                                    | `true`  | 是否可编辑                                                                                                |
| `showFlowEntry`    | `boolean`                                                                                    | `false` | 是否显示流程入口                                                                                          |
| `bkflowSaasUrl`    | `string`                                                                                     | -       | bkflow-saas-url，用于设置 `$.context.site_url` 的值，供插件内部使用                                       |
| `onConfirm`        | `(formData: { name: string, variablesValue: Record<string, any> }) => Promise<void> \| void` | -       | 自定义确定按钮回调（可选）                                                                                |
| `useCustomConfirm` | `boolean`                                                                                    | `false` | 是否使用自定义回调替代原有逻辑。为 `true` 时只执行 `onConfirm`，为 `false` 时在原有逻辑后执行 `onConfirm` |
| `onExecuteSuccess` | `(taskId: number, templateId: number) => void`                                               | -       | 执行成功回调（可选，仅在 `useCustomConfirm` 为 `false` 时生效）                                           |
| `enableVersion`    | `boolean`                                                                                    | `false` | 是否开启流程版本功能，开启后会根据 `flowVersion` 的值获取对应版本的流程数据                               |
| `flowVersion`      | `string`                                                                                     | -       | 流程版本号，仅在 `enableVersion` 为 `true` 时生效。为空时表示草稿版本，不为空时表示指定版本               |

#### Slots

| 插槽名                | 作用域参数                                                            | 说明                                 |
| --------------------- | --------------------------------------------------------------------- | ------------------------------------ |
| `custom-form-content` | `{ formData: { name: string }, variablesValue: Record<string, any> }` | 自定义表单内容，位于请求参数表单下方 |

#### Events

| 事件名         | 参数                                 | 说明                                                    |
| -------------- | ------------------------------------ | ------------------------------------------------------- |
| `confirm`      | `taskId: number, templateId: number` | 执行确认时触发（仅在 `useCustomConfirm` 为 `false` 时） |
| `close`        | -                                    | 关闭面板时触发                                          |
| `update:show`  | `show: boolean`                      | 显示状态更新时触发                                      |
| `before-close` | -                                    | 面板关闭前触发，用于清理数据                            |

#### 使用说明

- **自定义表单插槽**：可以在 `custom-form-content` 插槽中传入自定义的表单内容，插槽会接收 `formData` 和 `variablesValue` 作为作用域参数
- **自定义确定按钮回调**：
  - 当 `useCustomConfirm` 为 `false`（默认）时，`onConfirm` 会在原有的执行逻辑（创建任务并执行）完成后调用
  - 当 `useCustomConfirm` 为 `true` 时，点击确定按钮只会执行 `onConfirm` 回调，不会执行原有的创建和执行任务逻辑
- **表单验证**：无论使用哪种模式，都会先进行表单验证，验证通过后才会执行相应逻辑
- **版本控制**：当 `enableVersion` 为 `true` 时，会使用与 FlowView/FlowEdit 相同的版本数据获取逻辑，确保调试时使用正确版本的流程数据

---

## 使用示例

### 基础使用

```vue
<template>
  <FlowEdit
    :flow-id="flowId"
    :api-config="apiConfig"
    :permissions="{ canSave: true }"
    @save="handleSave"
    @save-success="handleSaveSuccess"
    @back="handleBack" />
</template>

<script setup>
  import { FlowEdit } from 'bkflow-canvas-editor';

  const flowId = '123';
  const apiConfig = {
    baseURL: window.API_HOST,
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };

  const handleSave = (flowData) => {
    console.log('保存流程:', flowData);
  };

  const handleSaveSuccess = () => {
    console.log('保存成功');
  };

  const handleBack = () => {
    // 返回处理
  };
</script>
```

### 使用自定义 InputParams 插槽

当需要自定义节点输入参数的渲染时，可以使用 `inputParams` 插槽：

```vue
<template>
  <FlowEdit
    ref="flowEditRef"
    :flow-id="flowId"
    :api-config="apiConfig"
    :permissions="{ canSave: true }"
    @save="handleSave">
    <!-- 自定义输入参数组件 -->
    <template
      #inputParams="{
        node,
        pluginDetail,
        inputs,
        editable,
        fullVariableList,
        updateInputParams,
        updateNodeInputParams,
      }">
      <CustomInputParams
        :node="node"
        :plugin-detail="pluginDetail"
        :inputs="inputs"
        :editable="editable"
        :full-variable-list="fullVariableList"
        @change="handleInputParamsChange($event, updateInputParams)" />
    </template>
  </FlowEdit>
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowEdit, type PluginInputDataItem } from "bkflow-canvas-editor";
  import CustomInputParams from "./components/CustomInputParams.vue";

  const flowEditRef = ref();
  const flowId = "123";
  const apiConfig = {
    baseURL: window.API_HOST,
    scopeData: {
      scope_type: "space",
      scope_value: 123,
    },
  };

  // 处理输入参数变化
  const handleInputParamsChange = (
    data: Record<string, PluginInputDataItem>,
    updateInputParams: (data: Record<string, PluginInputDataItem>) => void
  ) => {
    // 方式1：使用插槽提供的 updateInputParams 方法（推荐）
    // 这会暂存数据到节点配置面板，用户点击"确定"按钮后才会真正保存
    updateInputParams(data);

    // 方式2：通过 ref 调用组件方法（适用于需要在外部更新）
    // flowEditRef.value?.updateNodeInputParams(data);
  };
</script>
```

### 使用自定义 axios 实例

如果需要使用已配置好的 axios 实例（包含拦截器等），可以传入 `axiosInstance`：

```vue
<script setup>
  import { FlowView } from 'bkflow-canvas-editor';
  import http from '@/api'; // 你的 axios 实例

  const apiConfig = {
    axiosInstance: http, // 使用自定义 axios 实例
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

### 监听流程编辑状态

```vue
<template>
  <FlowEdit ref="flowEditRef" :flow-id="flowId" :api-config="apiConfig" @back="handleBack" />
</template>

<script setup>
  import { ref, watch } from 'vue';
  import { FlowEdit } from 'bkflow-canvas-editor';

  const flowEditRef = ref();

  // 监听流程编辑状态
  watch(
    () => flowEditRef.value?.isFlowEdited,
    (isEdited) => {
      if (isEdited) {
        console.log('流程已被编辑');
      }
    },
  );
</script>
```

### 使用自定义头部

```vue
<template>
  <FlowEdit :flow-id="flowId" :api-config="apiConfig">
    <template #header>
      <div class="custom-header">
        <h2>自定义头部</h2>
      </div>
    </template>
  </FlowEdit>
</template>
```

### 使用小地图模式

小地图模式适用于只需要展示画布内容的场景，不显示顶部 header 和操作按钮，禁用节点点击事件：

```vue
<template>
  <FlowView :flow-id="flowId" :api-config="apiConfig" :thumbnail="true" />
</template>

<script setup>
  import { FlowView } from 'bkflow-canvas-editor';
  import 'bkflow-canvas-editor/style';

  const flowId = '123';
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

### 使用流程版本功能

当需要查看、编辑或调试特定版本的流程时，可以使用版本功能：

```vue
<template>
  <!-- 查看指定版本的流程 -->
  <FlowView :flow-id="flowId" :api-config="apiConfig" :enable-version="true" :flow-version="'v1.0.0'" />

  <!-- 查看草稿版本的流程 -->
  <FlowView :flow-id="flowId" :api-config="apiConfig" :enable-version="true" />

  <!-- 编辑指定版本的流程 -->
  <FlowEdit :flow-id="flowId" :api-config="apiConfig" :enable-version="true" :flow-version="'v1.0.0'" />

  <!-- 调试草稿版本的流程 -->
  <FlowDebug :flow-id="flowId" :show="isDebugShow" :api-config="apiConfig" :enable-version="true" />

  <!-- 调试指定版本的流程 -->
  <FlowDebug
    :flow-id="flowId"
    :show="isDebugShow"
    :api-config="apiConfig"
    :enable-version="true"
    :flow-version="'v1.0.0'" />
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowView, FlowEdit, FlowDebug } from 'bkflow-canvas-editor';

  const flowId = '123';
  const isDebugShow = ref(false);
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

### 控制头部操作按钮显示

在 `FlowView` 组件中，可以通过 `showHeaderActions` props 控制头部操作按钮（编辑、执行流程、调试）的显示：

```vue
<template>
  <!-- 隐藏头部操作按钮 -->
  <FlowView :flow-id="flowId" :api-config="apiConfig" :show-header-actions="false" />
</template>

<script setup>
  import { FlowView } from 'bkflow-canvas-editor';

  const flowId = '123';
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

### 设置画布默认缩放比例

可以通过 `defaultZoom` props 控制 x6 画布的初始缩放比例，用于调整画布的默认显示效果：

```vue
<template>
  <!-- 设置画布默认缩放为 80% -->
  <FlowView :flow-id="flowId" :api-config="apiConfig" :default-zoom="0.8" />

  <!-- 设置画布默认缩放为 75% -->
  <FlowEdit :flow-id="flowId" :api-config="apiConfig" :default-zoom="0.75" />
</template>

<script setup>
  import { FlowView, FlowEdit } from 'bkflow-canvas-editor';

  const flowId = '123';
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

> **注意**：`defaultZoom` 的取值范围建议在 0.25 到 1.5 之间，这是 x6 画布配置的最小和最大缩放比例限制。

### 配置 quick-add 端口与插入方向

`FlowEdit` 支持透传 `quickAdd` 配置，能力与 `@blueking/flow-canvas` 的 `QuickAddConfig` 保持一致，可用于修改 quick-add 绑定的端口、点击插入方向，或直接关闭该交互。

```vue
<template>
  <FlowEdit
    :flow-id="flowId"
    :api-config="apiConfig"
    :quick-add="{
      portGroup: 'bottom',
      insertDirection: 'bottom',
    }" />
</template>
```

> **说明**：`FlowEdit` 只会在编辑态启用 quick-add；如果需要更底层的控制，也可以直接使用 `BkFlowCanvas` 并传入同名 `quickAdd` prop。

### 编辑态框选与批量删除

`FlowEdit` 在编辑态默认包含画布工具栏的框选能力。切换到框选模式后，鼠标在画布内拖拽会生成选区；当存在当前选区时，选区右下角会显示批量操作栏，当前内置操作为删除选中节点/边。

批量删除与键盘 `Delete` / `Backspace` 复用同一条底层删除链路，因此会保持一致的过滤和清理行为：

- 不可删除节点会按照节点行为配置统一过滤
- 网关 `conditions` / `defaultCondition` 会在删除时同步清理
- placeholder 相关级联删除会一并处理
- 删除成功后会自动清空当前选区并关闭批量操作栏

### 设置 bkflow-saas-url

可以通过 `bkflowSaasUrl` props 设置 `$.context.site_url` 的值，供插件内部使用：

```vue
<template>
  <FlowView :flow-id="flowId" :api-config="apiConfig" :bkflow-saas-url="'https://example.com/bkflow'" />

  <FlowEdit :flow-id="flowId" :api-config="apiConfig" :bkflow-saas-url="'https://example.com/bkflow'" />

  <FlowCreateTask
    :flow-id="flowId"
    :show="isExecuteShow"
    :api-config="apiConfig"
    :bkflow-saas-url="'https://example.com/bkflow'" />

  <FlowDebug
    :flow-id="flowId"
    :show="isDebugShow"
    :api-config="apiConfig"
    :bkflow-saas-url="'https://example.com/bkflow'" />
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowView, FlowEdit, FlowCreateTask, FlowExecute, FlowDebug } from 'bkflow-canvas-editor';

  const flowId = '123';
  const isExecuteShow = ref(false);
  const isDebugShow = ref(false);
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

> **说明**：`bkflowSaasUrl` 会被设置到 `window.$.context.site_url` 中，供插件内部使用。如果不提供，`site_url` 默认为空字符串。

### 禁用第三方插件

可以通过 `enableThirdPlugin` props 控制是否加载第三方插件。当设置为 `false` 时，将不加载第三方插件列表和详情，只显示内置插件：

```vue
<template>
  <FlowEdit :flow-id="flowId" :api-config="apiConfig" :enable-third-plugin="false" />
</template>

<script setup>
  import { FlowEdit } from 'bkflow-canvas-editor';

  const flowId = '123';
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

> **说明**：
>
> - `enableThirdPlugin` 默认值为 `true`，即默认启用第三方插件
> - 当设置为 `false` 时：
>   - 插件选择面板中的第三方插件标签将不会显示
>   - 不会请求第三方插件列表和详情
>   - 如果流程中已存在第三方插件节点，尝试打开节点配置时会提示错误
> - 也可以通过 `apiConfig.enableThirdPlugin` 来设置，效果相同

### 使用 FlowEdit 的调试功能

启用 FlowEdit 组件的调试功能，点击调试按钮会打开 FlowDebug 组件：

```vue
<template>
  <FlowEdit
    :flow-id="flowId"
    :api-config="apiConfig"
    :enable-debug="true"
    :on-debug-confirm="handleDebugConfirm"
    :use-custom-debug-confirm="false"
    @save="handleSave">
    <!-- 可选：自定义调试组件的表单内容 -->
    <template #debugCustomFormContent="{ formData, variablesValue }">
      <div class="custom-debug-form">
        <h4>自定义调试参数</h4>
        <bk-form-item label="调试模式">
          <bk-select v-model="debugMode">
            <bk-option label="快速调试" value="quick" />
            <bk-option label="完整调试" value="full" />
          </bk-select>
        </bk-form-item>
      </div>
    </template>
  </FlowEdit>
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowEdit } from 'bkflow-canvas-editor';

  const flowId = '123';
  const debugMode = ref('quick');
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };

  const handleSave = (flowData) => {
    console.log('保存流程:', flowData);
  };

  // 调试面板确定按钮回调（在原有逻辑执行后调用）
  const handleDebugConfirm = async (formData) => {
    console.log('调试任务已创建并执行');
    console.log('任务名称:', formData.name);
    console.log('变量值:', formData.variablesValue);
  };
</script>
```

#### 使用自定义调试回调（替代原有逻辑）

如果需要完全自定义调试面板的确定按钮行为，可以设置 `useCustomDebugConfirm` 为 `true`：

```vue
<template>
  <FlowEdit
    :flow-id="flowId"
    :api-config="apiConfig"
    :enable-debug="true"
    :on-debug-confirm="handleCustomDebugConfirm"
    :use-custom-debug-confirm="true"
    @save="handleSave" />
</template>

<script setup>
  import { FlowEdit } from 'bkflow-canvas-editor';

  const flowId = '123';
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };

  const handleSave = (flowData) => {
    console.log('保存流程:', flowData);
  };

  // 自定义调试回调（替代原有创建和执行任务逻辑）
  const handleCustomDebugConfirm = async (formData) => {
    console.log('执行自定义调试逻辑');
    console.log('任务名称:', formData.name);
    console.log('变量值:', formData.variablesValue);

    // 执行自定义逻辑，例如发送到调试服务
    // await sendToDebugService(formData);
  };
</script>
```

### 使用 FlowDebug 组件

#### 基础使用

```vue
<template>
  <FlowDebug
    :flow-id="flowId"
    :show="isDebugShow"
    :api-config="apiConfig"
    @close="isDebugShow = false"
    @update:show="isDebugShow = $event" />
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowDebug } from 'bkflow-canvas-editor';

  const flowId = '123';
  const isDebugShow = ref(false);
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

#### 使用自定义表单插槽

```vue
<template>
  <FlowDebug :flow-id="flowId" :show="isDebugShow" :api-config="apiConfig" @close="isDebugShow = false">
    <template #custom-form-content="{ formData, variablesValue }">
      <div class="custom-debug-form">
        <h4>自定义调试参数</h4>
        <bk-form-item label="调试模式">
          <bk-select v-model="debugMode">
            <bk-option label="快速调试" value="quick" />
            <bk-option label="完整调试" value="full" />
          </bk-select>
        </bk-form-item>
        <bk-form-item label="调试备注">
          <bk-input v-model="debugNote" placeholder="请输入调试备注" />
        </bk-form-item>
      </div>
    </template>
  </FlowDebug>
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowDebug } from 'bkflow-canvas-editor';

  const flowId = '123';
  const isDebugShow = ref(false);
  const debugMode = ref('quick');
  const debugNote = ref('');
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

#### 使用自定义确定按钮回调

```vue
<template>
  <FlowDebug
    :flow-id="flowId"
    :show="isDebugShow"
    :api-config="apiConfig"
    :use-custom-confirm="true"
    :on-confirm="handleCustomConfirm"
    @close="isDebugShow = false" />
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowDebug } from 'bkflow-canvas-editor';

  const flowId = '123';
  const isDebugShow = ref(false);
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };

  // 自定义确定按钮回调
  const handleCustomConfirm = async (formData) => {
    console.log('任务名称:', formData.name);
    console.log('变量值:', formData.variablesValue);

    // 执行自定义逻辑，例如发送到调试服务
    // await sendToDebugService(formData);

    // 关闭面板
    isDebugShow.value = false;
  };
</script>
```

#### 使用额外回调（不替代原有逻辑）

```vue
<template>
  <FlowDebug
    :flow-id="flowId"
    :show="isDebugShow"
    :api-config="apiConfig"
    :use-custom-confirm="false"
    :on-confirm="handleAdditionalConfirm"
    @close="isDebugShow = false" />
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowDebug } from 'bkflow-canvas-editor';

  const flowId = '123';
  const isDebugShow = ref(false);
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };

  // 额外回调：在原有执行逻辑完成后调用
  const handleAdditionalConfirm = async (formData) => {
    console.log('任务已创建并执行，执行额外逻辑');
    console.log('任务名称:', formData.name);
    console.log('变量值:', formData.variablesValue);

    // 例如：记录调试日志、发送通知等
  };
</script>
```

#### 使用版本控制的调试

```vue
<template>
  <!-- 调试草稿版本的流程 -->
  <FlowDebug
    :flow-id="flowId"
    :show="isDebugShow"
    :api-config="apiConfig"
    :enable-version="true"
    @close="isDebugShow = false" />

  <!-- 调试指定版本的流程 -->
  <FlowDebug
    :flow-id="flowId"
    :show="isDebugShow"
    :api-config="apiConfig"
    :enable-version="true"
    :flow-version="'v1.0.0'"
    @close="isDebugShow = false" />
</template>

<script setup>
  import { ref } from 'vue';
  import { FlowDebug } from 'bkflow-canvas-editor';

  const flowId = '123';
  const isDebugShow = ref(false);
  const apiConfig = {
    scopeData: {
      scope_type: 'space',
      scope_value: 123,
    },
  };
</script>
```

## API 配置

### FlowApiConfig

组件需要的 API 配置接口：

```typescript
interface FlowApiConfig {
  /** API 基础路径（可选，默认使用 window.API_HOST） */
  baseURL?: string;
  /** 自定义 axios 实例（可选，如果提供则优先使用） */
  axiosInstance?: AxiosInstance;
  /** axios 配置（可选，用于创建新的 axios 实例） */
  axiosConfig?: AxiosRequestConfig;
  /** CSRF cookie 名称（可选，用于创建新的 axios 实例时设置 xsrfCookieName） */
  xsrfCookieName?: string;
  /** 作用域数据（必需，由外部传入） */
  scopeData: {
    scope_type: string;
    scope_value: number;
  };
  /** 用户查询 API 地址（可选） */
  fetchUserApi?: string;
  /** 是否启用第三方插件（可选，默认为 true） */
  enableThirdPlugin?: boolean;
}
```

组件内部会自动实现所有 API 方法，包括：

- `fetchFlowDetail` - 获取流程详情
- `fetchFlowDraftDetail` - 获取流程草稿详情（可选，用于版本功能）
- `fetchFlowDetailByVersion` - 获取指定版本的流程详情（可选，用于版本功能）
- `fetchSpaceFlowConfig` - 获取空间配置
- `fetchSystemVariables` - 获取系统变量
- `saveFlow` - 保存流程（仅 FlowEdit）
- `fetchPluginGroupList` - 获取插件分类列表（仅 FlowEdit）
- `fetchCategoryPlugins` - 获取分类插件（仅 FlowEdit）
- `fetchPluginDetail` - 获取插件详情（可选）
- `fetchApplyInstructionData` - 获取指令数据（可选）
- `fetchVariableRef` - 获取变量引用（可选）
- `fetchCustomVariableTypes` - 获取自定义变量类型（可选）
- `fetchFlowOperateRecord` - 获取操作记录（可选）
- `createFlowTask` - 创建流程任务（可选）
- `executeFlowTask` - 执行流程任务（可选）

所有 API 请求会自动合并 `scopeData` 到请求参数中。

### 流程版本功能说明

当 `enableVersion` 为 `true` 时，FlowView、FlowEdit 和 FlowDebug 组件会使用版本相关的 API 来获取流程数据：

1. **总是先调用 `fetchFlowDetail`**：获取基础流程详情数据
2. **根据 `flowVersion` 的值决定是否调用版本接口**：
   - 如果 `flowVersion` 不为空：调用 `fetchFlowDetailByVersion` 获取指定版本的 `name` 和 `pipeline_tree` 字段，覆盖基础数据
   - 如果 `flowVersion` 为空：调用 `fetchFlowDraftDetail` 获取草稿版本的 `pipeline_tree` 字段，覆盖基础数据

这种设计确保了即使在使用版本功能时，也能获取到完整的流程基础信息，同时用版本特定的数据覆盖相应字段。

> **注意**：FlowEdit 组件会将 `enableVersion` 和 `flowVersion` 自动透传给内嵌的 FlowDebug 组件，因此在 FlowEdit 中启用版本功能后，调试面板也会自动使用对应版本的流程数据。

## 类型定义

所有类型定义都可以从包中导入：

```typescript
import type {
  FlowTemplate,
  SpaceFlowConfig,
  PluginGroupConfig,
  PluginMetaItem,
  UpdateFlowParams,
  FlowApiConfig,
  Variable,
  PipelineTree,
  Activity,
  PluginInputDataItem,
  UniformApiPluginInputsItem,
  PluginDetailCommon,
  SelectPanelConfig,
  QuickAddConfig,
  InsertDirection,
  // ... 更多类型
} from 'bkflow-canvas-editor';
```

> **注意**：`FlowViewApiConfig` 和 `FlowEditApiConfig` 是组件内部使用的类型，外部使用者只需要使用 `FlowApiConfig`。组件内部会通过 `useFlowApi` 自动将 `FlowApiConfig` 转换为所需的 API 方法接口。

## 本地开发

如果需要在当前项目中使用本地开发版本，可以在 `frontend/package.json` 中添加：

```json
{
  "dependencies": {
    "bkflow-canvas-editor": "file:../bkflow-canvas-editor"
  }
}
```

然后在 `frontend/vite.config.ts` 中添加别名：

```typescript
resolve: {
  alias: {
    'bkflow-canvas-editor': resolve(__dirname, '../bkflow-canvas-editor/src'),
  },
}
```

## 注意事项

1. **scopeData 必需**：`scopeData` 是必需的配置项，必须由外部传入，组件内部不会处理或设置默认值
2. **API 自动处理**：所有 API 调用由组件内部自动处理，无需手动实现 API 方法
3. **axios 实例优先级**：如果提供了 `axiosInstance`，组件会优先使用该实例；否则会根据 `baseURL` 和 `axiosConfig` 创建新的 axios 实例
4. **自动合并 scopeData**：所有 API 请求会自动合并 `scopeData` 到请求参数中（GET 请求合并到 params，POST/PUT 请求合并到请求体）
5. **权限检查**：权限检查通过 `permissions` props 传入布尔值
6. **路由跳转**：路由跳转需要通过事件回调处理，组件内部不直接使用 vue-router
7. **样式引入**：样式文件需要单独引入：`import 'bkflow-canvas-editor/style'`
8. **输入参数更新机制**：
   - 使用 `inputParams` 插槽时，通过 `updateInputParams` 或 `updateNodeInputParams` 方法更新的数据会暂存到节点配置面板
   - 用户需要点击节点配置面板的"确定"按钮，数据才会真正保存到流程中
   - 这种设计允许用户在保存前多次修改和预览
9. **API 配置类型说明**：
   - 外部使用者只需要使用 `FlowApiConfig` 类型
   - `FlowViewApiConfig` 和 `FlowEditApiConfig` 是组件内部使用的类型，通过 `useFlowApi` 自动转换
   - `FlowCreateTask` 和 `FlowDebug` 组件可以直接接受 `FlowApiConfig` 类型，组件内部会自动处理
10. **调试功能**：
    - `FlowEdit` 组件的 `enableDebug` props 默认为 `false`，设置为 `true` 后才会显示可点击的调试按钮
    - 点击调试按钮会打开 `FlowDebug` 组件，该组件提供了与 `FlowCreateTask` 相同的交互，但支持自定义表单插槽和自定义确定按钮回调
    - `FlowDebug` 组件的 `useCustomConfirm` 为 `false` 时，会先执行原有的创建和执行任务逻辑，然后执行 `onConfirm` 回调；为 `true` 时，只执行 `onConfirm` 回调
11. **版本控制**：
    - FlowView、FlowEdit、FlowDebug 三个组件均支持 `enableVersion` 和 `flowVersion` props
    - FlowEdit 会自动将版本相关 props 透传给内嵌的 FlowDebug 组件
    - 版本功能依赖 `fetchFlowDraftDetail` 和 `fetchFlowDetailByVersion` 两个 API 方法

## License

MIT
