# 智连云工作流前端核心库

# installation
```shell
# 使用npm 安装
$ npm install -D @smart-link/workflow-core
# 使用yarn 安装
$ yarn add -D @smart-link/workflow-core
```


# flow designer 流程设计器
基于@antv/g6的流程设计器, 满足了智连云流程设计的所有功能
```javascript
import {FlowDesigner} from '@smart-link/workflow-core';

const designer = new FlowDesigner(options)
```

## FlowDesigner Options

- **container**: 画布容器，为HTML元素
- **width**: 画布宽度, 默认为container的宽度
- **height**: 画布高度, 默认为container的高度

- **itemWrapper**: 待选流程节点元素父容器，为HTML元素，dom结构参考如下 ,其中 element 中的 data-item 属性为流程节点的初始化数据
```html
<div class="item-wrapper">
    <div class="element" draggable="true" data-item="{clazz: 'START', size: '50*50', label: '开始'}">开始</div>
    <div class="element" draggable="true" data-item="{clazz: 'END', size: '50*50', label: '结束'}">结束</div>
    <div class="element" draggable="true" data-item="{clazz: 'NORMAL', size: '90*40', label: '正常任务'}">正常任务</div>
    <div class="element" draggable="true" data-item="{clazz: 'PARALLEL_SIGN', size: '90*40', label: '并签任务'}">并签任务</div>
    <div class="element" draggable="true" data-item="{clazz: 'SERVICE', size: '90*40', label: '服务任务'}">服务任务</div>
</div>
```

- **itemSelector**: 待拖选流程元素节点选择器，如上 itemWrapper 中的 .element 元素

- **flowTypes**: 流向类型数据, 流程节点之间的连线, 可以为连线填充颜色

```json
[
  {
    "val": "同意",
    "extVal": "#00ff00"
  },
  {
    "val": "不同意，结束",
    "extVal": "#ff0000"
  },
  {
    "val": "退回修改",
    "extVal": "#ffff00"
  }
]
```

- **toolbar**: 工具栏容器，为HTML元素，支持的命令 如下
    - 'undo'
    - 'redo'
    - 'copy'
    - 'delete'
    - 'zoomIn'
    - 'zoomOut'
    - 'resetZoom'
    - 'autoFit'

dom结构如下
```html
<div class="toolbar">
    <button class="command" data-command="undo">撤销</button>
    <button class="command" data-command="redo">重做</button>
    <button class="command" data-command="copy">复制</button>
    <button class="command" data-command="delete">删除</button>
    <button class="command" data-command="zoomIn">放大</button>
    <button class="command" data-command="zoomOut">缩小</button>
    <button class="command" data-command="resetZoom">重置缩放</button>
    <button class="command" data-command="autoFit">适应画布</button>
</div>
```

- **mode**: 设计器模式，用来区分设计器行为
    - default 可以拖动画布、点击选中元素
    - view 可以拖动画布、点击选中元素、鼠标悬浮提示
    - edit 可以拖动画布、点击选中元素、可以拖动元素、从选区添加元素节点、添加节点连线、以及可执行工具栏命令

- **defaultData** 默认流程数据，设计器会根据默认数据化自动添加节点和连线, 结构如下
```js
const defaultData = {
  "nodes": [
    {
      clazz: 'START',
      size: [50, 50],
      label: '开始',
      shape: 'start-node',
      id: 'startEvent-1586419748018'
    },
    {
      clazz: 'NORMAL',
      size: [90, 40],
      label: '填报申请单',
      shape: 'normal-node',
      x: 234,
      y: 150,
      id: 'process-node-1586419956248',
      defCategory: 'NORMAL',
    }      
  ],
  "edges": [
    {
      clazz: 'flow',
      source: 'startEvent-1586419748018',
      target: 'process-node-1586419956248',
      sourceTaskDefKey: 'startEvent-1586419748018',
      tarTaskDefKey: 'process-node-1586419956248',
      sourceAnchor: 2,
      id: 'Flow-0',
      targetAnchor: 0,
      flowName: '开始',
    }
  ]
}

```

- **tooltip**: 自定义鼠标悬浮提示

```js
    const tooltip = {
        formatText(model){ // 格式化提示文本内容
            return 'string';
        },
        shouldBegin: e => { // 是否对元素节点进行提示
            let model = e.item.getModel();
            return !/START|END/.test(model.clazz)
        },
    }
```
- **events**:
```js
    const events = {
        onSelectedItem(id, model){}, // 元素被选中，可以对元素进行属性编辑
        onBlurItem(){}, // 元素失去焦点
        onUpdateToolbar(commands){}, // 当前可用命令
        onValidateError(model, info){}, // 流程元素校验出错
    }
```

## FlowDesigner 实例方法
### designer.save(needValid: boolean): GraphData
返回流程设计数据: {tasks: {}, flows: {}}
- 参数 needValid 是否需要校验节点数据完整性


### designer.initData(data?: GraphData, dynamicTasks?: any, options?: {flowTypes})
初始化流程数据
- 参数 data 为流程设计数据： {tasks: {}, flows: {}}
- 参数 dynamicTasks 流程动态数据，如流程过程中的处理人，处理时间
- 参数 options 类型与实例化时相同，主要传入流向类型数据

### designer.update(key: string, cfg: object, isBatch = false)
更新当前选中节点的配置信息
- key 当前更新的键名
- cfg 具体更新的配置对象，可以一次修改多个属性，
- isBatch 是否批量更新，存在节点之间关联修改配置时可以开启

## 在 Vue项目中使用
```vue
<!--App.vue-->
<template>
  <div class="flow-designer">
    <div class="toolbar" ref="toolbar">
      <button class="command" data-command="undo">撤销</button>
      <button class="command" data-command="redo">重做</button>
      <button class="command" data-command="copy">复制</button>
      <button class="command" data-command="delete">删除</button>
      <button class="command" data-command="zoomIn">放大</button>
      <button class="command" data-command="zoomOut">缩小</button>
      <button class="command" data-command="resetZoom">重置缩放</button>
      <button class="command" data-command="autoFit">适应画布</button>
    </div>
    <div class="canvas" ref="canvas"></div>
    <div class="item-wrapper" ref="itemWrapper">
      <div class="element" draggable="true" data-item="{clazz: 'START', size: '50*50', label: '开始'}">开始</div>
      <div class="element" draggable="true" data-item="{clazz: 'END', size: '50*50', label: '结束'}">结束</div>
      <div class="element" draggable="true" data-item="{clazz: 'NORMAL', size: '90*40', label: '正常任务'}">正常任务</div>
      <div class="element" draggable="true" data-item="{clazz: 'PARALLEL_SIGN', size: '90*40', label: '并签任务'}">并签任务</div>
      <div class="element" draggable="true" data-item="{clazz: 'SERVICE', size: '90*40', label: '服务任务'}">服务任务</div>
    </div>
  </div>
</template>
<script>
import {FlowDesigner} from '@smart-link/workflow-core';

export default {
  name: 'App',
  data() {},
  mounted() {
    this.designer = new FlowDesigner({
      container: this.$refs.canvas,
      itemWrapper: this.$refs.itemWrapper,
      itemSelector: '.element',
      toolbar: this.$refs.toolbar,
      mode: 'edit',
      flowTypes: [],
      tooltip: {
        formatText(model) {
          return '角色: ' + (model?.roleIds[0]?.roleName || '-') +
                  '<br/> 处理人: ' + (model?.assigneeNames || '-') +
                  '<br /> 备注: ' + (model?.remark || '-');
        },
        shouldBegin: e => {
          let model = e.item.getModel();
          return !/START|END/.test(model.clazz)
        },
      },
    })
  }
}
</script>

```