## 自定义流程图

### 功能

- 新增节点，新增可新增条件节点和流程节点
- 删除节点
- 修改节点，点击查看后弹出抽屉进行节点属性的编辑
- 多选，按住shift键合并生成控制节点
- 反选，流程节点可反选，菜单中选择反选目标节点
- 保存位置，拖拽后保存位置
- 缩放和画布拖拽
- 实现流程节点的颜色配置（失败/成功/正常/开始/结束）
- 流程图中是否可以点击mask关闭抽屉
- 流程图界面的mask颜色配置
- 流程图界面的宽高配置
- 抽屉的宽度配置
- 返回了节点选择改变的事件
- 返回了更新节点数据的方法    
- 返回了切换抽屉状态的方法
- 返回了获取当前流程图数据的方法
- 新增删除反选按钮是否展示的配置
- 新增菜单中条件节点的配置
- 新增菜单中选项文案的配置
- 删除节点的方法
- 所有前置节点的方法

### 安装

推荐使用 npm 的方式安装，它能更好地和 webpack 打包工具配合使用

`npm i jkstack-flow-chart`

### 引入

#### 根据需要可以选择再文件中引入，或者全局引入

##### 1.文件引入，在使用得vue文件中引入

```vue
<script>
import FlowChart from 'jkstack-flow-chart' // 引入组件
import 'jkstack-flow-chart/dist/flow-chart.css' // 引入组件样式

export default {
  components: {
    FlowChart
  }
}
</script>

```

##### 2.全局引入，在main.js中全局引入

```vue

import FlowChart from 'jkstack-flow-chart' // 引入组件
import 'jkstack-flow-chart/dist/flow-chart.css' // 引入组件样式

Vue.use(FlowChart)

```


### 快速上手

```vue
<template>
  <div id="app">
    <FlowChart
      ref="flowChart"
      :data="data"
      :height="height"
      :width="width"
      :closeSideBarClickMask="false"
      :maskColor="maskColor"
      :statusColor ="statusColor"
      addFlowNodeText="流程节点"
      addSwitchNodeText="条件节点"
      :showDelBtn="true"
      :showAddBtn="true"
      :showBackBtn="false"
      :shoViewBtn="false"
      :addShowSwitchNode="false"
      @node-selected="nodeSelecSted"
      @node-add="nodeAdd"
      @node-delete="nodeDel"
    >
    <!-- 插槽 -->
      <template v-slot:sideBar>
        <div class="rightMsg">
          <div v-if="selectedNodes.type === 'flowNode'">
            <div class="title">流程节点</div>
            <input type="text" v-model="selectedNodes.label" placeholder="请输入标题">
            <input type="text" v-model="selectedNodes.propertyOne" placeholder="节点属性">
            <input type="text" v-model="selectedNodes.propertyTwo" placeholder="节点属性">
            <input type="text" v-model="selectedNodes.propertyThree" placeholder="节点属性">
            <input type="text" v-model="type" placeholder="各个项目中所存储的参数(类型)">
            <input type="text" v-model="tell" placeholder="各个项目中所存储的参数(方式)">
            <input type="text" v-model="people" placeholder="各个项目中所存储的参数(对象)">
            <Button @click="saveNodeData">保存节点数据</Button>
            <Button @click="closeSidebar">取消</Button>
          </div>
          <div v-if="selectedNodes.type === 'switchNode'">
            <div class="title">条件节点</div>
            <input type="text" v-model="type" placeholder="各个项目中所存储的参数(类型)">
            <input type="text" v-model="tell" placeholder="各个项目中所存储的参数(方式)">
            <input type="text" v-model="people" placeholder="各个项目中所存储的参数(对象)">
            <Button @click="saveNodeData">保存节点数据</Button>
            <Button @click="closeSidebar">取消</Button>
          </div>
          <div v-if="selectedNodes.type === 'controlNode'">
            <div class="title">控制节点</div>
            <input type="text" v-model="type" placeholder="各个项目中所存储的参数(类型)">
            <input type="text" v-model="tell" placeholder="各个项目中所存储的参数(方式)">
            <input type="text" v-model="people" placeholder="各个项目中所存储的参数(对象)">
            <Button @click="saveNodeData">保存节点数据</Button>
            <Button @click="closeSidebar">取消</Button>
          </div>
        </div>
      </template>
    </FlowChart>
    <button @click="getData">保存流程图数据</button>
  </div>
</template>

<script>
import FlowChart from './components/FlowChart.vue' // 引入组件
// import FlowChart from 'jkstack-flow-chart' // 引入组件
// import 'jkstack-flow-chart/dist/flow-chart.css' // 引入组件

export default {
  name: 'App',
  components: {
    FlowChart
  },
  data () {
    return {
      selectedNodes: {},
      statusColor: { // 状态颜色得配置
        success: { color: '#67C23A' }, // 成功
        error: { color: '#F56C6C' }, // 失败
        normal: { color: '#409EFF' }, // 正常
        start: { color: '#909399' }, // 开始
        end: { color: '#909399' } // 结束
      },
      width: 1500, // 宽度
      height: 600, // 高度
      maskColor: 'rgba(255, 255, 255, 0.7)', // mask颜色
      data: {}, // 流程图数据
      type: '', // 各个项目中所需存储得字段
      tell: '', // 各个项目中所需存储得字段
      people: '' // 各个项目中所需存储得字段
    }
  },
  methods: {
    // 选择节点事件
    nodeSelecSted (node) {
      this.selectedNodes = node // 拿到当前点击得节点数据
    },
    // 新增节点事件
    nodeAdd (node) {
      console.log('新增', node)
      this.selectedNodes = node
    },
    // 删除节点事件
    nodeDel (node) {
      console.log('删除', node)
    },
    // 保存节点数据
    saveNodeData () {
      if (this.selectedNodes) {
        this.selectedNodes.task = { // *各个项目需求中所存储得内容请放进task对象
          type: this.type,
          tell: this.tell,
          people: this.people
        }
        this.$refs.flowChart.updateItem(this.selectedNodes) // 更新图表节点方法调用，传入更改后得节点信息
        this.$refs.flowChart.toggleSidebar() // 调用更改抽屉状态的方法
      }
    },
    // 更改抽屉关闭/打开状态
    closeSidebar () {
      this.$refs.flowChart.toggleSidebar()
    },
    // 获取流程图数据保存
    getData () {
      console.log(this.$refs.flowChart.getData()) // 获取流程图中数据调用getData()方法
    }
  }
}
</script>

<style lang="scss" scoped>
#app{
  width: 1500px;
  border:1px solid #fff;
  border-radius: 5px;
  margin: 20px auto;
}
.rightMsg{
  padding: 20px;
  box-sizing: border-box;
}
.title{
  font-size: 15px;
  margin-bottom: 10px;
  color: #666;
}
input{
  width: 100%;
  border: 1px solid #efefef;
  line-height: 35px;
  padding: 0 10px;
  box-sizing: border-box;
  border-radius: 8px;
  font-size: 14px;
  outline: none;
}
textarea{
  width: 100%;
  border: 1px solid #efefef;
  line-height: 35px;
  padding: 10px;
  box-sizing: border-box;
  border-radius: 8px;
  font-family: '微软雅黑';
  font-size: 14px;
  outline: none;
}
button{
  width: 120px;
  height: 45px;
  line-height: 45px;
  text-align: center;
  background: #3388FF;
  color: #fff;
  border: none;
  border-radius: 5px;
  font-size: 16px;
  margin: 10px 20px;
}
</style>


```



### API

##### FlowChart Attributes

| 参数                 | 说明                                                              | 类型   | 默认值                 |
| -------------------- | ---------------------------------------------------------------- | ------ | ---------------------- |
| width                | 指定画布宽度，单位为 'px'                                          | number | 1200                   |
| height               | 指定画布高度，单位为 'px'                                          | number | 600                    |
| sliderWidth          | 指定抽屉宽度，单位为 'px'                                          | number | 400                    |
| data                 | 显示的图表数据 [配置项](#data)                                     | object | {nodes: [], edges: []} |
| closeSideBarClickMask| 是否可以通过点击 mask 关闭抽屉                                     | boolean | true                   |
| maskColor            | mask遮罩层的颜色                                                  | string  | rgba(0,0,0,0.3)        |
| statusColor          | 节点状态颜色 (success/error/normal/start/end)                     | object  | [默认值](#节点状态颜色默认值)|
| showBackBtn          | 是否展示反选按钮                                                  | boolean | true                   |
| showAddBtn           | 是否展示新增按钮                                                  | boolean | true                   |
| showDelBtn           | 是否展示删除按钮                                                  | boolean | true                   |
| showViewBtn           | 是否展示查看按钮                                                  | boolean | true                   |
| addFlowNodeText      | 新增菜单中新增流程节点得文案                                       | string  | 新建流程节点            |
| addShowSwitchNode    | 新增菜单中是否展示‘新增条件节点’                                   | boolean | true                   |
| addSwitchNodeText    | 新增菜单中新增条件节点得文案                                       | string  | 新建条件节点            |


###### 节点状态颜色默认值
```js
statusColor: {
  success: { color: '#67C23A' }, 
  error: { color: '#F56C6C' }, 
  normal: { color: '#409EFF' }, 
  start: { color: '#909399' }, 
  end: { color: '#909399' }
}
```


##### FlowChart Events

| 事件名           | 说明                                                             | 参数 |
| --------------- | ---------------------------------------------------------------- | ---- |
| node-selected   | 当用户手动点击当前节点查看按钮触发的事件                             | node |
| node-add        | 当用户手动点击新增节点和合并控制节点时触发的事件                      | node |
| node-delete     | 当用户手动删除节点时触发的事件                                      |  -   |

##### FlowChart Methods

| 方法名           | 说明                                          | 参数   |
| --------------- | --------------------------------------------- | ------ |
| deleteItem      | 用于删除关联的节点                             |  nodeId  |
| updateItem      | 用于更新节点数据                               |  node  |
| getAllPreNodeList| 用于返回所有前置节点                           |  nodeId  |
| fitView         | canvas适应视口                                 |  padding: [top, right, bottom, left]  |
| toggleSidebar   | 用于切换抽屉的状态                              |    -    |
| getData         | 用于用户获取当前数据                            |    -    |


##### FlowChart Slot

| slot name       | 说明                                                                                         |
| --------------- | -------------------------------------------------------------------------------------------- |
| sideBar         | 抽屉的内容，如果需要编辑当前节点，需要自定义 dom ，并且提交数据的时候调用 updateItem 方法更新节点信息｜



##### data
- 数据格式如下，分为nodes(节点)和edges(关系)，

```js
data: {
      nodes: [
        {
          id: 'start',
          type: 'flowNode',
          label: '开始',
          state: 'start',
          x: 100,
          y: 100,
          propertyOne: '节点属性',
          propertyTwo: '节点属性',
          propertyThree: '节点属性',
          task: {}
        },
        {
          id: 'xxx1',
          type: 'switchNode',
          label: '第一个节点',
          state: 'normal',
          x: 480,
          y: 100,
          propertyOne: '节点属性',
          propertyTwo: '节点属性',
          propertyThree: '节点属性',
          task: {}
        },
        {
          id: 'xxx2',
          type: 'controlNode',
          label: '第二个节点',
          state: 'normal',
          x: 480,
          y: 140,
          propertyOne: '节点属性',
          propertyTwo: '节点属性',
          propertyThree: '节点属性',
          task: {}
        }
      ],
      edges: [
        {
          source: "start",
          target: "xxx1",
          type: "customEdge"
        },
        {
          source: "xxx1",
          target: "xxx2",
          type: "customBackEdge"
        }
      ]
  }
```



#### 节点（nodes）

| 属性                                  | 说明                                                                | 备注    |
| ------------------------------------- | ------------------------------------------------------------------ | ------- |
| id                                    | 节点得唯一标识                                                      | 不可更改 |
| type                                  | 节点类型(流程节点:flowNode/条件节点:switchNode/控制节点:controlNode)  | 不可更改 |
| label                                 | 节点标题                                                            |    -    |
| state                                 | 节点状态(成功：success/异常：error/正常：normal/开始：start/结束：end) |    -    |
| x                                     | 相对canvas得X坐标                                                   | 不可更改 |
| y                                     | 相对canvas得y坐标                                                   | 不可更改 |
| propertyOne/propertyTwo/propertyThree | 节点属性                                                            |    -    |
| task                                  | 根据需求所需绑定该节点得属性，请添加进task,避免组件与业务混淆           |    -    |
| anchorPoints                          | 节点入口/数组                                                        | 不可更改 |
| style                                 | 节点样式/对象                                                        | 不可更改 |


#### 边（edges）

| 属性               | 说明                                                  | 备注   |
| ----------------- | ----------------------------------------------------- | ------- |
| source            | 源ID                                                  | 不可更改 |
| target            | 目标ID                                                 | 不可更改 |
| targetAnchor      | 源坐标索引值                                            | 不可更改 |
| sourceAnchor      | 目标坐标索引值                                          | 不可更改 |
| type              | 类型(自定义边：customEdge/自定义反选边：customBackEdge)  | 不可更改 |
| style             | 边样式                                                 | 不可更改 |
| startPoint        | 源出口坐标                                             | 不可更改 |
| endPoint          | 目标入口坐标                                           | 不可更改 |
