Skip to content

业务表单示例 ​

概述 ​

业务表单示例是工作流(BPM)模块中一个端到端的业务表单样例,用于演示「业务表单 + 流程引擎」的完整接入方式:业务数据存储在独立的业务表中,审批流程由工作流引擎驱动,审批结果通过引擎事件回写到业务表。

业务表单示例——请假申请涉及三大部分:前端页面、业务接口、流程引擎。三者通过「流程定义标识 oa_leave」与「流程实例编号 process_instance_id」关联。

后端实现 ​

后端代码位于 backend/app/api/v1/module_bpm/oa_leave/,采用与系统其它模块一致的分层结构:controller → service → crud + model + schema,并通过 listener.py 订阅引擎事件。

业务表与数据模型 ​

业务表 bpm_oa_leave 记录一次请假申请的核心字段,并通过 process_instance_id 与流程实例绑定。

字段说明
user_id申请人用户编号(数据权限按本人 OWN)
type请假类型,字典 bpm_oa_leave_type(病假/事假/婚假…)
reason请假原因
start_time / end_time起止时间(毫秒时间戳存取)
day请假天数,由引擎计算 (end - start).days
status审批结果,复用 BpmProcessInstanceStatusEnum(审批中/通过/不通过/取消)
process_instance_id关联流程实例编号(核心外键)

模型定义见 backend/app/api/v1/module_bpm/oa_leave/model.py

接口与权限 ​

路由前缀 /bpm/oa/leave,标签「工作流-OA请假申请」,需登录鉴权:

接口说明权限码
POST /create创建请假申请并发起流程bpm:oa-leave:create
GET /get获取请假申请详情bpm:oa-leave:query
GET /page分页查询请假申请bpm:oa-leave:query

创建并发起流程 ​

BpmOALeaveService.create 是核心入口:先做基础校验(结束时间必须晚于开始时间),再查询 key=oa_leave 的最新激活版本流程定义,计算请假天数,调用引擎 create_instance 同事务发起流程,最后落库业务单。

python
# service.py(节选)
PROCESS_KEY = "oa_leave"

day = (data.end_time - data.start_time).days
engine = BpmProcessEngine(self.auth)
instance = await engine.create_instance(
    definition,
    {"day": day, "type": data.type, "reason": data.reason},  # 流程变量
    data.start_user_select_assignees,                         # 发起人自选审批人
)
leave = BpmOALeaveModel(
    user_id=self.auth.user.id,
    type=data.type, reason=data.reason,
    start_time=data.start_time, end_time=data.end_time,
    day=day, status=BpmProcessInstanceStatusEnum.RUNNING,
    process_instance_id=instance.id,
)

其中 day 作为流程变量传入引擎,供条件分支节点求值使用(例如「请假天数 > 3 天需总监审批」)。start_user_select_assignees 对应前端「发起人自选审批人」策略,结构为 {节点ID: [用户编号]}。

审批结果回写(监听器) ​

流程审批结束时,引擎发布 PROCESS_INSTANCE_FINISH 事件,业务层订阅该事件将审批结果回写到请假单。模块导入时即完成订阅(见 router.py 中的 from ...oa_leave import listener)。

python
# listener.py(节选)
async def on_process_instance_finish(instance, status: int, reason: str | None = None, **_) -> None:
    """流程实例终态:按实例编号回写请假单审批结果"""
    rows = (await session.execute(
        select(BpmOALeaveModel).where(BpmOALeaveModel.process_instance_id == instance.id)
    )).scalars().all()
    for leave in rows:
        leave.status = status

event.subscribe(event.BpmEventEnum.PROCESS_INSTANCE_FINISH, on_process_instance_finish)

这种「事件解耦」设计让业务表与流程引擎互不侵入:业务无需感知审批节点细节,引擎也无需知道具体业务语义。

取消流程 ​

当请假单处于「审批中」时,发起人可在前端取消。后端 process_instance 模块提供 cancel_by_start_user,并兼容以业务单据编号(即请假单 id)取消——内部通过 BpmOALeaveService.resolve_instance_id 回退解析出流程实例编号。

python
# process_instance/service.py(节选)
async def cancel_by_start_user(self, id: int, reason: str) -> None:
    instance = await BpmProcessInstanceCRUD(self.auth).get(id=id)
    if instance is None:
        # 业务表单场景:兼容前端以业务单据编号取消流程
        instance_id = await BpmOALeaveService(self.auth).resolve_instance_id(id)
        ...

流程定义配置 ​

请假流程在「流程模型」中维护,关键属性:

  • 流程标识(Key):oa_leave,与后端 PROCESS_KEY 一致,引擎据此查找定义。
  • 表单类型:业务表单(自定义路由)。
  • 条件分支:利用流程变量 day 配置分支条件,例如天数较小时仅部门负责人审批,天数较大时追加总监审批。
  • 发起人自选审批人:若某审批节点候选策略设为 START_USER_SELECT,前端会在发起页让用户选择具体审批人。

流程绘制与节点配置详见《流程模型》《流程框架》章节。

前端实现 ​

页面结构 ​

前端位于 apps/web-ele/src/views/bpm/oa/leave/,配套 API 在 apps/web-ele/src/api/bpm/oa/leave/index.ts。页面基于 Vben Admin 的 Page + VxeTable + useVbenForm 组件,并复用流程实例的「审批进度时间线」组件。

image-20261001111033159

视图文件作用
请假列表index.vue分页列表、发起/详情/审批进度/取消/重新发起
发起 / 重新发起create.vue填写表单 + 实时预览审批流
请假详情detail.vue展示业务字段
表单与列定义data.ts表单项、搜索项、表格列、详情项 schema

发起页与流程预览 ​

image-20261001111046347

create.vue 是体验的核心:左侧填写业务表单,右侧通过 ProcessInstanceTimeline 实时展示审批节点。发起页在 onMounted 时拉取 key=oa_leave 的流程定义,并调用审批详情接口预测节点。

关键交互:

  • 表单中输入起止时间后,watch 会重新预测审批节点(因为条件分支依赖 day)。
  • 若存在「发起人自选审批人」节点,右侧时间线会提示用户选择具体审批人。
  • 提交时把 startUserSelectAssignees 一并传给后端。
ts
// create.vue(节选)
const processDefineKey = 'oa_leave'; // 流程定义 Key
const submitData: LeaveCreateData = {
  ...data,
  startTime: Number(data.startTime),
  endTime: Number(data.endTime),
};
if (startUserSelectTasks.value?.length > 0) {
  submitData.startUserSelectAssignees = startUserSelectAssignees.value;
}
await createLeave(submitData);

时间字段与字典 ​

  • 起止时间使用 DatePicker,valueFormat: 'x'(毫秒时间戳),与后端 MillisecondDateTime 类型互转保持一致。
  • 请假类型、审批结果均用字典渲染:BPM_OA_LEAVE_TYPE、BPM_PROCESS_INSTANCE_STATUS,在 data.ts 中通过 getDictOptions 与 CellDict 配置。

列表操作 ​

index.vue 中的行操作根据状态动态展示:

  • 审批中(RUNNING):显示「取消」。
  • 非审批中:显示「重新发起」。
  • 始终提供「详情」「审批进度」,审批进度跳转到流程实例详情页查看时间线。

端到端流程演示 ​

其它业务表单 ​

若需把工作流接入其它业务(如报销、采购),可参照本示例:

  1. 新建业务表与 Model,通过 process_instance_id 关联流程实例,权限策略按需设置。
  2. 编写 Service:create 中调用 BpmProcessEngine.create_instance,并传入业务变量。
  3. 编写 listener:订阅 PROCESS_INSTANCE_FINISH,按 process_instance_id 回写业务状态。
  4. 在 router.py 中导入 listener 模块完成订阅注册。
  5. 前端仿照 views/bpm/oa/leave/,用 processDefineKey + 审批详情预测组件接入发起页。