本示例位于 flow-api、flow-core 的独立 leave 包,业务表为 flow_ext_leave。不修改引擎原生表,不依赖 UPM 实体和 Service;申请人身份通过 WorkflowIdentityProvider 获取。
OA审批的默认菜单顺序为:流程定义(1)、我的待办(2)、我的已办(3)、我发起的(4)、请假申请(5)。后续业务页面从5及之后排序,不插到前四个公共入口中;本次只固定默认排序,不更改既有菜单的 operable 或授权状态。
页面支持本人申请列表、状态筛选、新建、编辑草稿、删除草稿、提交申请、退回修改及原实例重新提交、业务详情和审批进度。审批人在“我的待办”打开实例时,可通过“请假申请”页签读取正文;正文不存放在流程变量中,也不根据客户端URL加载。
已有库在完成审批中心菜单和操作权限迁移后,停写、备份,再执行对应的 sql/migration/20261019_flow_leave.mysql.sql 或 .postgres.sql 一次。脚本创建业务表,为模板租户新增菜单和五个按钮,并校正公共入口的默认排序;其他租户同步应用菜单、授权后重新登录。MySQL 5.7兼容,不使用窗口函数,也不在一条语句中重复引用临时表。
新库只执行最新全量脚本。脚本不创建、发布或修改任何流程定义,也不自动创建测试单据。必须在当前租户存在已发布、启用且有有效办理人的流程。
请假示例需宿主显式启用,infra-start 已默认开启。只依赖通用 flow-core 的其他服务默认不加载请假接口和业务关联,不会因为查看通用实例而访问请假表。需要接入示例时配置:
flow.leave.enabled=true
flow.leave.flow-code=leave
相同编码的定义按租户隔离,不共享另一租户的流程。流程编码由服务端在创建草稿时写入,浏览器不能指定或覆盖;调整配置不改变已有草稿的绑定。
本版不推算节假日、午休或排班,也不把“自然时长”自动当作“工作时长”。例如09:00至18:00可以按排班填8小时。暂不包含余额扣减、附件和通知。动态部门主管已通过通用办理人规则接入,配置步骤见动态办理人配置。
需要退回修改的请假流程,配置为:开始 → 提交申请 → 本部门审核 → 上一级部门审核 → 结束。
首次在业务表单点击“提交申请”,后端在启动流程的同一事务中自动完成该申请节点,直接进入审核,无需申请人再去待办“审核自己”。只自动完成这一节点,绝不因为后续办理人恰好是申请人而自动跳过审核。
审核退回申请节点后,申请人可从“请假申请”列表或“我的待办 → 办理申请”打开表单,修改后“保存修改”或“重新提交”。保存只更新单据,不推进流程;重新提交继续原实例并保留此前审批记录,不另建实例。通用详情在此节点不展示“通过 / 退回”,服务端也会拒绝使用通用审批接口绕过业务校验。
审批进行中,申请人可在“我发起的”使用“拿回”,将流程退回到本人最近完成的节点;拿回到“提交申请”后即可修改并重新提交原实例。对仍在办理中的申请也可“撤销”,实例随后标记为已撤销且不能继续审批;撤销不等同于拿回,不保留可编辑的待办申请节点。是否显示按钮由实例当前状态决定,后端仍会校验发起人身份和活动状态。
旧的“开始 → 审批 → 结束”流程仍可直接提交;没有申请节点的定义不会自动增加节点。只回到审核节点的退回仍是审核,不会开放业务表单编辑。
| 接口 | 权限 | 用途 |
|---|---|---|
GET /flow/leave/page |
flow:leave:list |
本人分页,status可为DRAFT或引擎状态 |
GET /flow/leave/detail/{id} |
请假列表或任一审批中心查询权限 | 查看正文,仍校验本人或实例参与身份 |
POST /flow/leave/add |
flow:leave:add |
保存新草稿,不启动流程 |
POST /flow/leave/edit/{id} |
flow:leave:edit |
修改本人草稿或当前申请节点单据,须携带version;后者还须携带submissionTaskId |
POST /flow/leave/submit/{id} |
flow:leave:submit |
首次提交或原实例重提,须携带version;重提还须携带submissionTaskId |
POST /flow/leave/delete/{id} |
flow:leave:delete |
物理删除本人草稿,须携带version |
新建示例:
{
"leaveType": "PERSONAL",
"startTime": "2026-10-20 09:00:00",
"endTime": "2026-10-20 18:00:00",
"durationHours": 8,
"reason": "外出办事"
}
响应中保留 id、version。编辑时提交完整业务字段及当前版本;首次提交和删除的请求体为 {"version": 1}。每次编辑、提交后版本都会更新,不能一直复用旧版本。
详情和列表通过 editable、submissionTaskId 告知当前是否可编辑及对应申请任务。退回修改时,编辑请求在上述完整业务字段基础上增加 submissionTaskId;使用编辑响应中的新版本重新提交,例如:
{
"version": 3,
"submissionTaskId": "2100000000000000001"
}
editable 只用于界面展示,不是授权凭证。写入时服务端重新校验当前任务、租户、本人、候选身份和版本;缺少或过期的任务ID会被拒绝。任务已进入审核、实例已完成或挂起时不能修改;有实例的单据始终不能删除。非本人读取正文时,必须属于该实例当前候选人或历史办理人;平台管理员不默认绕过参与身份。列表始终只显示当前租户本人记录。
首次提交在READ_COMMITTED事务中锁定本人草稿,校验版本和未提交状态,调用 WorkflowService.start、绑定实例ID,再自动完成申请节点。任一步失败整笔回滚,草稿保留、实例不残留;包括自动完成后无法生成有效审核任务的情况。同一草稿并发提交最多启动一个实例。
修改已发起单据和重新提交时,先锁流程实例,再锁业务单据,与通用审批遵循一致的实例串行化边界;重提同时增加单据版本并推进原任务,失败共同回滚。外层业务事务也必须使用READ_COMMITTED,共用数据源及事务管理器。重提更新类型、时长等业务路由变量,但不覆盖发起时固化的动态办理人快照。
instance_id 为空即草稿;提交后的状态实时关联 flow_instance.flow_status,不在业务表重复维护一份审批状态。无需额外编写“每个节点完成就审批通过”的监听器。流程变量仅包含业务类型、申请人ID、请假类型、时长等必要路由数据,不包含请假原因。
业务通过 WorkflowBusinessProvider 向审批中心提供受信任的类型、单据ID和标题;findSubmissionTask 额外识别该业务的申请任务,控制待办入口及通用审批拦截。业务Service校验和保存表单后,在同一事务内调用 WorkflowService.submitBusinessTask,该方法仍校验实际候选身份及业务类型,不开放通用HTTP提交入口。新增其他业务时可提供自己的关联实现和受保护正文接口,不需要在通用引擎表中追加业务字段。
本次退回重提不新增表、字段或权限按钮;已完成请假表及菜单迁移的数据库无需重复执行SQL。申请人需要原有的编辑、提交按钮权限;不需要通用审批通过权限来提交业务申请。
flow-core 的宿主,重新登录并确认菜单排序及权限。leave 已发布,审批节点已配置有效办理人。集成测试覆盖完整退回重提、自动提交失败的事务回滚及并发重提只成功一次;前端组件测试覆盖首次动态打开表单、不可编辑状态、提交失败重试不重复保存。浏览器模拟接口回归覆盖创建、审核退回、原表单修改重提、最新正文及移动端抽屉,不读写真实业务库。