### 基于 SdWebflow 组件开发'通用审批'表单

开发过程

<img src="assets/flowform-1.jpg">

详情接口返回的表单字段（打开待办时会自动调用接口）

```javascript
api/framework/v1/task-form-process/todo-pages/${id}
```

<img src="assets/flowform-2.jpg">

字段属性，包括字段名,字段 label,是否只读，是否必填，控件类型等

<img src="assets/flowform-4.jpg">

### 1. 在目录 src_product 下添加目录 tylc

注意项目上的模块应该在 src_custom 目录下开发,这里为了演示用了 product 目录

### 2. 基于 sdWebflow 添加流程表单组件 oa-tylc.vue

_可使用内置插件快速创建 vue 组件文件_，见 [新建 vue 文件](#新建vue文件)

最基本的使用方式就是在 form slot 中绘制审批单

```vue
<template>
  <sd-webflow>
    <template v-slot:form>
      <table>
        <tr>
          <sd-form-item-td name="title" :colspan="3" />
        </tr>
        <tr>
          <sd-form-item-td name="mainSendUnit" :colspan="3" />
        </tr>
        <tr>
          <sd-form-item-td name="creationTime" />
          <sd-form-item-td name="creatorName" />
        </tr>
      </table>
    </template>
  </sd-webflow>
</template>

<script>
export default {
  isFlowFormExample: true, // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

说明：表单中的标签 sd-form-item-td 组件 可以理解为增强版的 td 标签，它能根据接口返回的字段类型自动渲染 label 和对应的前端组件，比如人员部门选择器，单选复选下拉框等，包括是否必填，只读等。 <br><br> 另外除了自动渲染方式，你也可以自定义字段的渲染，具体见 [sd-form-item-td](#sdformitemtd)

### 3. 注册表单组件

因为流程详情接口打开业务类型是不固定的，有可能是印章申请也有可能是车辆申请，为了让流程详情接口找到对应的审批单，我们需要将接口返回的 pageId 和审批表单建立对应关系。在模块目录下添加 index.js 文件，添加如下代码

```javascript
import asyncComponent from '@/common/services/async-component'
import flowService from '@/webflow/flow-service'
// 两个参数： 接口返回的pageId、流程表单组件
flowService.addFlowForm('vue:demo/contract/oaContract', './oa-tylc.vue')
```

如上，调用平台方法 flowService.addFlowForm，只需要传入对应的 pageId 和表单组件，这样当我打开一条待办或起草文件时，系统则会根据接口返回的 pageId 打开对应的审批单

### 4. 扩展按钮事件 actionBtnClick

除了平台标准的转办、知会、驳回等功能外，我们也会开发自定义的业务功能，或者覆盖平台的标准功能。这时我们可以用扩展 ，实现自己或覆盖平台的按钮功能。

```vue
<template>
  <sd-webflow @actionBtnClick="actionBtnClick">
    <template v-slot:form>
      <table>
        <tr><sd-form-item-td name="title" :colspan="3"/></tr>
        <tr><sd-form-item-td name="mainSendUnit" :colspan="3"/></tr>
        <tr><sd-form-item-td name="creationTime"/><sd-form-item-td name="creatorName"/></tr>
      </table>
    </template>
  </sd-webflow>
</template>

<script>
import { Modal } from 'ant-design-vue'
export default {
  methods: {
    actionBtnClick(evt, { button, FlowData }) {
      // button包含按钮信息，flowdata包含流程上下文信息

      /*
      button.buttonId 是后台返回的按钮ID，其中保存、提交按钮的值都是动态的，不方便做判断
      button.fakeId 是前端整理过的ID，例如：保存按钮的值永远都是save
      */
      switch (button.fakeId) {
        case 'customid':
          // 自定义的按钮，自己实现相关业务
          break
        case 'workflow$inform':
          // 平台的知会按钮，自己实现功能，覆盖平台的代码
          evt.preventDefault()
          alert('这里放我自己接管的知会逻辑')
          break
        case 'workflow$turnToDo':
          // 平台的转办按钮，自己实现定制功能（这里是异步的）后再走平台的代码
          evt.waitUntil(
            new Promise((resolve) => {
              Modal.confirm({
                content: '是否确认要转办？',
                onOk() {
                  // 异步操作完成，通知逻辑继续往下走
                  resolve()
                },
                onCancel() {
                  // 停止原有逻辑
                  evt.preventDefault()
                  // 标识异步操作完成
                  resolve()
                },
              })
            })
          )
          break
        default:
          break
      }
    },
  },
  isFlowFormExample: true, // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

### 5. 扩展表单校验 validate-form

一些联合校验场景可能会用到，比如 3 个字段有 1 个填了就可以，这种不适合对单个字段校验的可以用扩展 validate-form

_更多可参考 product 目录里其他的业务功能代码_

```vue
<template>
  <sd-webflow ref="flow" :validate-form="validForm">
    </template>
    <template v-slot:form>
      <table>
        <tr><sd-form-item-td name="title" :colspan="3"/></tr>
        <tr><sd-form-item-td name="mainSendUnit" :colspan="3"/></tr>
        <tr><sd-form-item-td name="creationTime"/><sd-form-item-td name="creatorName"/></tr>
      </table>
    </template>
  </sd-webflow>
</template>

<script>
export default {
    methods: {
      validForm() {
        // 自定义校验，适用于多个字段联合校验，支持promise
        if (this.$refs.flow.getFieldValue('open') === '0') {
          // 是否公开===不公开
          alert('校验失败')
          return Promise.resolve(false)
        } else {
          return Promise.resolve(true)
        }
      },
    },
  isFlowFormExample: true,  // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

### 6. Tab 页的扩展：增加/删除

删除 tab 页、插入到指定位置时，需要传入现有的 tab 页 id。现有的 tab 页如下：

- sdForm 表单
- sdLog 流程跟踪
- sdRelatedDoc 关联文档
- sdFlowchart 流程图

```vue
<template>
  <!--  删除流程图tab页 -->
  <sd-webflow :removed-tabs="['sdFlowchart']">
    <template v-slot:extra-tabs="{ FlowData }">
      <a-tab-pane key="currentStep" tab="当前环节信息">
        <!-- FlowData中包含整个流程相关的信息 -->
        <a-card> 当前处理人：{{ FlowData.processActiveLogInfo[0].operator }} </a-card>
      </a-tab-pane>
      <!-- 增加的tab页默认在最后，通过sd-before、sd-after可以指定位置 -->
      <a-tab-pane key="other" tab="测试" sd-before="sdLog">
        <a-card>一些内容</a-card>
      </a-tab-pane>
    </template>
    <template v-slot:form>
      <table>
        <tr><sd-form-item-td name="title" :colspan="3"/></tr>
        <tr><sd-form-item-td name="mainSendUnit" :colspan="3"/></tr>
        <tr><sd-form-item-td name="creationTime"/><sd-form-item-td name="creatorName"/></tr>
      </table>
    </template>
  </sd-webflow>
</template>

<script>
export default {
  isFlowFormExample: true, // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

### 7. 按钮位置调整

审批单按钮分三个区域：顶部、提交区、其他。项目可以根据需求把按钮调整到任意区域。

由于顶部按钮区域需要图标，所以把按钮放到顶部的时候，需要通过 `buttonIcons` prop 指定对应的图标。

具体每个按钮的 ID 是什么，可以通过接口返回值查看

特例：下面的几个按钮 ID 是动态的，所以按此约定替换

- 保存按钮 save，
- 流程提交按钮 workflow-push
- 管理员操作 admin-ops

```vue
<template>
  <!--
  通过 headerButtons 定制哪些按钮显示在顶部
  通过 submitButtons 往提交区域增加了驳回按钮
  通过 buttonIcons 更换了关闭按钮的图标
   -->
  <sd-webflow
    :headerButtons="['we-doc$print', 'save', 'we-doc$close']"
    :submitButtons="['workflow-push', 'workflow$interfere']"
    :buttonIcons="{ 'we-doc$close': 'close' }"
  >
    <template v-slot:form>
      <table>
        <tr><sd-form-item-td name="title" :colspan="3"/></tr>
        <tr><sd-form-item-td name="mainSendUnit" :colspan="3"/></tr>
        <tr><sd-form-item-td name="creationTime"/><sd-form-item-td name="creatorName"/></tr>
      </table>
    </template>
  </sd-webflow>
</template>

<script>
export default {
  isFlowFormExample: true, // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

### 8. 在 Tab 页内增加内容

通过各 Tab 页的内容区 Slot，可以在指定 Tab 页插入新的内容

显示的顺序则可以通过 `data-order` 属性指定（已有内容的排序值，可以用调试工具查看 DOM 结构）

```vue
<template>
  <sd-webflow>
    <template v-slot:log-tab-bottom="{ FlowData }">
      <a-card size="small" title="这是扩展的内容" data-order="150">
        activeStepId：{{ FlowData.activeStepId }}
      </a-card>
    </template>
    <template v-slot:form>
      <table>
        <tr><sd-form-item-td name="title" :colspan="3"/></tr>
        <tr><sd-form-item-td name="mainSendUnit" :colspan="3"/></tr>
        <tr><sd-form-item-td name="creationTime"/><sd-form-item-td name="creatorName"/></tr>
      </table>
    </template>
  </sd-webflow>
</template>

<script>
export default {
  isFlowFormExample: true, // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

### 9. 自定义显示流转记录、流程图等组件显示位置

流转记录、知会记录、流程图等是独立的组件，可直接使用，项目可灵活展示到不同的位置

- sd-flowchart 流程图
- sd-inform-log, 知会记录
- sd-process-info, 流转记录
- sd-opinion-log, 意见记录
- sd-reminder-log, 催办记录
- sd-modify-log, 修改记录
- sd-relate-doc, 关联文件

```vue
<template>
  <sd-webflow>
    <template v-slot:form>
      <table class="sd-form-table">
        <tr><sd-form-item-td name="title" :colspan="3"/></tr>
        <tr><sd-form-item-td name="mainSendUnit" :colspan="3"/></tr>
        <tr><sd-form-item-td name="creationTime"/><sd-form-item-td name="creatorName"/></tr>
      </table>

      <sd-process-info />
    </template>
  </sd-webflow>
</template>

<script>
export default {
  isFlowFormExample: true, // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

### 10. 打印业务单，自定义默认显示项

审批意见、流转记录、知会记录等在打印业务单时默认是不显示的，需要用户在显示项中勾选才能显示。项目可定制哪些显示项默认勾选

显示项的 id 如下：

- sd-opinion-log 审批意见
- sd-process-info 流转记录
- sd-inform-log 知会记录
- sd-reminder-log 催办记录
- sd-modify-log 修改记录
- sd-relate-doc 关联文件
- sd-flowchart 流程图

```vue
<template>
  <!--
    通过 defaultPrintBlocks 定制哪些显示项默认勾选
  -->
  <sd-webflow :default-print-blocks="['sd-opinion-log', 'sd-process-info']">
    <template v-slot:form>
      <table class="sd-form-table">
        <tr><sd-form-item-td name="title" :colspan="3"/></tr>
        <tr><sd-form-item-td name="mainSendUnit" :colspan="3"/></tr>
        <tr><sd-form-item-td name="creationTime"/><sd-form-item-td name="creatorName"/></tr>
      </table>
    </template>
  </sd-webflow>
</template>

<script>
export default {
  isFlowFormExample: true, // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

### 11. 打印业务单，添加自定义显示项

打印业务单时除产品默认可显示的内容(业务表单、审批意见、流转记录等)外，项目可定制添加扩展的内容

扩展的内容如需被显示项控制（即默认不显示，在显示项中勾选时显示），则需使用组件 sd-webflow-print-block，属性说明如下：

- key 显示区域的 key；显示项中的 value
- title 显示区域的 title；显示项中的 label
- data-order 显示区域的排序值

扩展的内容显示的顺序可以通过 `data-order` 属性指定（已有内容的排序值，可以用调试工具查看 DOM 结构）

```vue
<template>
  <sd-webflow>
    <template v-slot:print-content-bottom>
      <!-- sd-webflow-print-block组件的内容会被显示项控制，在显示项中勾选时才显示 -->
      <sd-webflow-print-block key="xm-ext-log" title="扩展内容" :data-order="230">
        <div>扩展的内容1</div>
      </sd-webflow-print-block>
      <!-- 直接显示在打印单中，不会被显示项控制显示或隐藏 -->
      <div :data-order="110">扩展的内容2</div>
    </template>
    <template v-slot:form>
      <table class="sd-form-table">
        <tr><sd-form-item-td name="title" :colspan="3"/></tr>
        <tr><sd-form-item-td name="mainSendUnit" :colspan="3"/></tr>
        <tr><sd-form-item-td name="creationTime"/><sd-form-item-td name="creatorName"/></tr>
      </table>
    </template>
  </sd-webflow>
</template>

<script>
export default {
  isFlowFormExample: true, // 这行给开发手册使用的，拷贝后请去掉
}
</script>
```

### 12. 通用/共性需求处理

上面的样例都是针对某一个业务单的定制，如果我们需要在所有业务单上定制一些功能，该怎么办呢？

可以通过 [流程表单模板](#extwebflowtemplate) 来实现

其使用方法与上面样例都是类似的，区别只是写在不同的文件中
