移动端审批
友情提示
本文讲解 yudao 移动端(uni-app 版)的工作流审批,重点说清楚三件事:移动端 BPM 的代码结构、流程表单、业务表单。
- 仓库:https://github.com/yudaocode/yudao-ui-admin-uniapp (opens new window),基于
uni-app+Vue3+wot-ui实现,支持 H5、微信小程序等多端。 - 后端:复用 PC 端同一套
yudao-module-bpm模块与/bpm/**接口,移动端只是换了一层 UI。
# 1. Vue 文件的作用
移动端 BPM 的代码分布在三个目录:
src/pages/bpm/:审批中心入口,放在主包(switchTab的 Tab 页必须在主包)。src/pages-bpm/:其余 BPM 页面,是一个独立分包(pages.json的subPackages)。
和审批、表单相关的核心文件如下:
| 文件 / 目录 | 作用 |
|---|---|
pages/bpm/index.vue | 审批中心入口,含「待办任务 / 已办任务 / 我的流程 / 抄送我的」四个 Tab |
pages-bpm/processInstance/create/index.vue | 发起流程:按分类选择要发起的流程 |
pages-bpm/processInstance/create/form.vue | 发起流程:填写流程表单并提交 |
pages-bpm/processInstance/detail/index.vue | 审批详情页:基本信息、表单、审批进度、底部操作栏 |
pages-bpm/processInstance/detail/components/form-detail.vue | 表单展示组件,流程表单 / 业务表单都由它渲染 |
pages-bpm/processInstance/detail/components/operation-button.vue | 底部操作栏:通过、拒绝、转办、加签等操作入口 |
pages-bpm/processInstance/detail/audit/index.vue | 审批「同意 / 拒绝」的提交页 |
pages-bpm/processInstance/detail/{return,reassign,copy,add-sign,delete-sign,process-cancel}/ | 退回、转办 / 委派、抄送、加签、减签、取消 各操作子页 |
pages-bpm/components/form-create/ | form-create 移动版,把流程表单的 JSON 配置渲染成界面 |
pages-bpm/oa/leave/ | OA 请假,BPM 自带的业务表单示例 |
src/api/bpm/ | 接口层,和 PC 端共用一套 /bpm/** 接口 |

后面两节聚焦其中最关键的一条线 —— 表单。BPM 有两种表单,由流程定义的 formType 区分:
- 流程表单(
formType = 10):见第 2 节。 - 业务表单(
formType = 20):见第 3 节。
# 2. 流程表单
流程表单,是在 PC 端 [流程设计器] 里用拖拽的方式设计出来的动态表单,不需要写代码。它的配置(formConf)和字段(formFields)存在流程定义上,移动端拿到后用 form-create 渲染。
- 渲染组件:
pages-bpm/components/form-create/(form-create 的 wot-ui 移动版)。 - 渲染入口:通过
setConfAndFields2(...)把formConf、formFields、表单变量喂给<FormCreate>。
它出现在两个地方:
① 发起时填写,对应 pages-bpm/processInstance/create/form.vue:

② 审批时展示,对应 form-detail.vue 中 formType === NORMAL 的分支。审批详情页还会根据后端返回的字段权限,把每个字段设置为只读 / 可编辑 / 隐藏(不同审批节点可以不一样):

PC 端流程表单的接入,可进一步参考 《审批接入(流程表单)》 文档。
# 3. 业务表单
业务表单,是各业务模块自己写的页面(不是拖出来的),比如 OA 请假、CRM 合同。流程定义上只存它在 PC 端的路径(formCustomCreatePath 发起页、formCustomViewPath 详情页)。
移动端的页面路径和 PC 端不一样,所以需要一张「PC 路径 → 移动端路径」的映射表,见 pages-bpm/utils/index.ts:
const PC_TO_MOBILE_PATH_MAP: Record<string, string> = {
// OA 请假(同分包,内嵌)
'/bpm/oa/leave/create': '/pages-bpm/oa/leave/create/index',
'/bpm/oa/leave/detail': '/pages-bpm/oa/leave/detail/index',
// CRM 合同审批(跨分包,仅详情,跳转)
'/crm/contract/detail': '/pages-crm/contract/detail/index',
// CRM 回款审批(跨分包,仅详情,跳转)
'/crm/receivable/detail': '/pages-crm/receivable/detail/index',
}
审批详情页(form-detail.vue)拿到 PC 路径后,用 getMobileFormCustomPath(...) 查这张表,得到移动端页面。
这里有个关键区别:业务表单页有的放在 pages-bpm、有的放在 pages-crm,两者的接入方式完全不同。 根本原因不在 BPM,而在 uni-app 分包机制 + 微信小程序限制:移动端每个业务模块是一个独立分包(pages-bpm、pages-crm……),审批页住在 pages-bpm;业务表单页归属哪个模块就放哪个分包 —— OA 请假是 BPM 自带的,放 pages-bpm;CRM 合同 / 回款属于 CRM,放 pages-crm。
# 3.1 pages-bpm 下的业务表单(同分包,内嵌)
以 OA 请假 为例。它和审批详情页同在 pages-bpm 分包,同分包可以直接 import 组件,所以审批详情页把它当普通组件内嵌进来,审批时原地就能看到完整的请假表单:
<!-- form-detail.vue:同分包,直接内嵌 -->
<LeaveDetail v-if="isSamePackageForm" :id="processInstance?.businessKey" embedded />

可以看到,请假类型、起止时间、请假原因等业务字段,直接内嵌展示在审批详情页里。
# 3.2 pages-crm 下的业务表单(跨分包,跳转)
以 CRM 合同 / 回款 为例。它在 pages-crm 分包,和审批页跨分包。微信小程序不支持跨分包 import 组件,没法内嵌,于是退一步:审批详情页只放一个「查看业务表单详情」入口,点击后用 uni.navigateTo 跳转到 pages-crm 的详情页(跨分包路由跳转是允许的):
<!-- form-detail.vue:跨分包,改为跳转 -->
<view v-else-if="businessDetailPath" @click="openBusinessDetail">查看业务表单详情</view>

和 OA 请假不同,审批详情页这里不内嵌业务表单,只显示一个「查看业务表单详情」入口;点击后跳转到 pages-crm 的合同详情页:

是同分包还是跨分包,由 isSamePackage(...) 比较两个页面路由的第一段(pages-bpm / pages-crm)自动判断。
想让 CRM 这类业务表单也内嵌展示?
内嵌的前提是「同分包」。如果希望某个业务表单(比如 CRM 合同)也能像 OA 请假那样直接内嵌进审批详情页、而不是跳转,就需要把它的移动端页面挪到 pages-bpm 分包下(和审批页同分包),再参考 3.1 静态 import 内嵌。否则跨分包就只能走 3.2 的跳转方案。
小结
同分包能内嵌、跨分包只能跳转。 新增一个移动端业务表单时:如果页面放在 pages-bpm 内,可参考 OA 请假内嵌;如果在别的分包(如 pages-crm),就只能像 CRM 合同那样,配置映射后跳转。
PC 端业务表单的接入,可进一步参考 《审批接入(业务表单)》 文档。