Skip to content

通用审核系统:用 X6 画出审批流程

git: https://github.com/fengnovo/universal-audit
线上地址:https://universal-audit.keen-tech.top/designer?mode=demo&name=费用报销流程&owner=财务共享中心

最近整理了一个通用审核系统前端演示项目。它不连接真实后端接口,不接数据库,也不包含登录鉴权,而是用前端页面模拟审批工作台、流程管理、流程编排、待办已办和发起审批这些核心场景。

项目使用 Next.js、React、Tailwind CSS、AntV X6 和 lucide-react 实现。它更像一个产品原型和交互样板:先把审批系统里最重要的角色、页面和流程编排体验做出来,再把后端流转和数据存储留给后续接入。

先用大白话理解

审批系统可以先不要想得太复杂。它本质上就是三件事:

1. 先定规则管理员先建一个审批流程模板,比如费用报销流程。
2. 再画步骤流程管理员用 X6 画出开始、审批人、条件判断、通知和结束。
3. 员工提交普通员工发起一张申请单,选择审批类型并填写金额、部门、说明。
4. 系统派任务系统按流程模板,把审批任务流转给对应审批人。
5. 审批人处理审批人在待办里点通过或驳回,流程继续或结束。

所以这套系统不是单纯做几张表单,而是在表达一个核心关系:流程模板定义规则,申请单触发规则,审批任务按规则流转。

系统解决什么问题

通用审核系统用于管理公司里的审批事项:

  • 普通员工提交审批申请。
  • 审批人查看待办任务,并处理通过或驳回。
  • 管理员创建和维护审批流程。
  • 流程管理员在流程编排页面中,把审批步骤像画图一样画出来。

它的核心流转可以概括为:

text
先建流程 -> 再画步骤 -> 员工提交 -> 审批人处理

这也是审核系统的主干:流程模板定义规则,申请单触发实例,审批任务按规则流转。

从角色看,几类用户关心的东西完全不同:

普通员工只关心怎么发起审批、提交后流程会走到哪里。
审批人只关心待办里有哪些任务,需要通过还是驳回。
管理员关心有哪些流程模板、谁负责维护、当前是否启用。
流程管理员关心流程步骤怎么画、节点怎么配置、连线怎么转向。

这个项目做得比较清楚的一点,是没有把所有功能塞到一个页面里,而是按角色拆成工作台、流程管理、流程编排、待办已办和发起审批。

页面结构

项目里有五个主要页面。

审核工作台

访问 /,默认进入审核工作台。这个页面展示待处理任务、运行中流程、本月通过率、平均处理时长、最近待办、流程健康度和最近提交。

如果你是审批人,优先看最近待办;如果你是管理员,优先看运行中流程和流程健康度。

流程管理

访问 /processes,展示流程模板列表。每一行代表一个审批流程模板,包含流程名称、负责人、版本、状态、节点数和操作。

点击“新建流程”会打开弹窗,填写流程名称、负责人和流程类型后,点击“创建并编排”,系统会进入流程设计器,并加载一个新建流程骨架。

流程编排

访问 /designer,这是项目最核心的页面。左侧是节点库,中间是 X6 画布,右侧是节点或连线属性面板,顶部提供撤销、重做、适配、清空和导出。

节点库里有开始、审批人、会签、条件判断、抄送通知和结束节点。流程管理员可以把节点拖到画布里,再通过端口连线。

待办已办

访问 /tasks,审批人可以看到审批任务列表。列表包含审批事项、金额、状态、时效和操作按钮。通过按钮表示同意,驳回按钮表示不同意。

发起审批

访问 /apply,普通员工填写审批类型、申请金额、申请部门、期望完成日期、审批标题、申请说明和附件。右侧会展示预计流转路径。

这五个页面可以用一张图串起来:

审核工作台/看待办、运行中流程、通过率、流程健康度和最近提交。
流程管理/processes维护审批流程模板,新建流程后进入编排页面。
流程编排/designer用 X6 画节点和连线,是整个演示项目的核心。
待办已办/tasks审批人查看任务,执行通过或驳回。
发起审批/apply员工填写申请表单,右侧展示预计流转路径。
本地存储localStorage保存侧边栏状态和新建流程草稿,不代表真实后端。

流程编排的交互设计

流程设计器启动时,会先创建 X6 画布,然后注册选择、键盘、剪贴板、历史记录和对齐线插件。

如果地址参数里没有新建模式,系统加载默认演示流程;如果包含:

text
mode=new

则加载新建流程骨架。这个骨架包含开始节点、审批节点和结束节点,避免用户从完全空白的画布开始。

最基础的编排动作是:

text
从左侧拖节点 -> 放到画布 -> 拖动端口创建连线 -> 编辑节点和连线属性

比如:

text
开始 -> 审批人 -> 结束

表示申请提交后,先进入审批人处理,然后流程结束。

设计器里的操作可以拆成这条流水线:

进入设计器创建 X6 画布,注册选择、键盘、剪贴板、历史记录和对齐线插件。
加载初始流程demo 模式加载默认流程,new 模式加载开始、审批、结束骨架。
拖入节点从左侧节点库拖到画布,系统按鼠标位置创建节点。
拖动端口连线从一个节点的小圆点拖到另一个节点的小圆点,生成流转箭头。
编辑属性点击节点或连线,右侧面板修改名称、审批人、条件、起点和终点。
导出 JSON把画布上的节点和边变成结构化数据,留给后端保存和执行。

大白话说:X6 画布负责让人“画得出来”,右侧属性面板负责让规则“说得清楚”,导出 JSON 负责让后端“读得懂”。

节点属性

点击画布中的任意节点,右侧会显示节点属性。常见配置包括:

  • 节点名称
  • 审批人或角色
  • 条件表达式
  • 通知对象
  • 备注说明

不同节点代表不同审批步骤:

  • 开始:流程起点。
  • 审批人:某个人或某个角色处理。
  • 会签:多个人一起审批。
  • 条件判断:按金额、部门等条件分支。
  • 抄送通知:给相关人发送通知。
  • 结束:流程终点。

修改节点名称后,画布中的节点文字会同步更新。这让属性面板不只是表单,而是和画布形成了实时联动。

这些节点可以按职责理解:

开始申请提交后的流程入口,通常只有一条出边。
审批人指定某个人或某个角色来处理这一步。
会签多个人一起审批,适合多人共同确认的场景。
条件判断按金额、部门、类型等条件决定走哪条分支。
抄送通知流程不一定停在这里,但会通知相关人。
结束流程终点,申请通过、驳回或完成都会落到这里。

节点本身表示“这一步做什么”,节点属性表示“这一步由谁做、按什么条件做、要通知谁”。

连线属性为什么重要

很多流程设计器只重视节点属性,但这个项目里连线属性也被单独做出来了。点击已有连线后,右侧会显示:

  • 连线文字
  • 起点节点
  • 起点端口
  • 终点节点
  • 终点端口

这解决了一个很实际的问题:用户手动拖拽连线手柄,有时很难准确命中目标端口。更稳定的做法是选中连线后,在右侧属性面板里通过下拉框改起点、终点和端口。

比如原来是:

text
开始 -> 审批节点

想改成:

text
开始 -> 审批人

可以选中连线,在右侧把“终点节点”改成“审批人”,再选择终点端口。对复杂审批流来说,这种属性化编辑比纯拖拽更可控。

连线不是视觉装饰,它就是审批流转方向:

节点表示审批步骤,例如部门经理审批。
连线表示下一步去哪里,例如通过后去财务审批。
连线属性说明从哪个节点、哪个端口,连到哪个节点、哪个端口。

为什么要做连线属性面板?因为复杂流程里,靠鼠标拖动端点很容易接错。下拉框改起点和终点虽然看起来笨一点,但更稳定,也更适合做流程维护。

导出 JSON

点击“导出 JSON”后,系统会读取当前画布中的节点和连线,并导出结构化数据。

导出内容包含:

  • nodes:节点编号、节点类型、节点名称、审批人、条件表达式、备注和坐标。
  • edges:连线编号、起点、终点和连线文字。

这里其实已经隐含了后端接入方式:前端负责把流程画成节点和边,后端可以保存这份 JSON,并在真实审批实例中根据节点和连线驱动流转。

这个边界和工作流系统很像:画布是编辑态,JSON 是协议,后端运行时消费协议。

导出的 JSON 可以理解成两张表:

nodes

记录有哪些审批步骤:节点 ID、节点类型、名称、审批人、条件表达式、备注、坐标。

edges

记录步骤之间怎么走:边 ID、起点、终点、连线文字和端口信息。

后端运行时

未来可以读取 nodes 和 edges,按规则创建审批任务并推动流程流转。

举个最简单的例子:

json
{
  "nodes": [
    { "id": "start_1", "type": "start", "label": "开始" },
    { "id": "approve_1", "type": "approver", "label": "部门经理审批", "assignee": "部门经理" },
    { "id": "end_1", "type": "end", "label": "结束" }
  ],
  "edges": [
    { "source": "start_1", "target": "approve_1", "label": "提交" },
    { "source": "approve_1", "target": "end_1", "label": "通过" }
  ]
}

这段数据的意思很直白:申请提交后先到部门经理,部门经理通过后流程结束。前端画的是图,后端真正需要保存的是这份结构化规则。

本地演示边界

这个项目明确是前端演示项目。所有列表数据都是静态模拟数据,新建流程只保存在当前浏览器本地。

本地存储主要保存两类内容:

  • 侧边栏折叠状态。
  • 流程管理中新建的流程草稿。

刷新页面后,流程管理会重新读取这些本地流程草稿;如果清空浏览器本地存储,新建流程草稿也会消失。

这种设计适合产品演示和交互验证。它先把流程管理、流程编排、待办处理和发起申请这些前端体验跑顺,不急着把后端模型一次性做重。

本地演示和真实系统的边界可以这样看:

当前演示已有页面结构、静态数据、流程编排交互、节点/连线属性、JSON 导出、本地草稿。
当前演示没有真实登录鉴权、后端接口、数据库、审批实例运行时、消息通知和权限控制。
为什么这样做先验证产品路径和设计器交互,避免一开始就被后端流程引擎拖慢。
以后怎么接把导出 JSON 存成流程模板,申请单创建审批实例,审批任务按 edges 流转。

这不是缺点,反而是这个项目目标清楚的地方:它先把“审批系统长什么样、流程怎么画”讲明白。

常用操作

流程设计器支持一些典型快捷操作:

  • 撤销:Ctrl + Z
  • 重做:Ctrl + Shift + Z
  • 复制节点:选中后 Ctrl + C
  • 粘贴节点:Ctrl + V
  • 删除节点或连线:选中后按 Delete
  • 缩放画布:按住 CtrlCommand 滚动鼠标滚轮
  • 平移画布:按住 Space 后拖动画布

这些快捷键让设计器更像一个真正的工作台,而不是只能点按钮的页面。

我喜欢的几个点

第一,角色路径清楚。员工、审批人、管理员、流程管理员各自关心的页面不同,产品结构没有混在一起。

第二,流程编排以节点和连线为核心。审批系统天然适合图模型,节点表示步骤,连线表示流转方向。

第三,连线属性面板做得很实用。对复杂流程来说,靠下拉框改端点比拖动手柄更稳定。

第四,导出 JSON 把前后端边界留出来了。前端可以先完成编排体验,后端以后接保存、发布、执行和版本管理。

第五,演示项目没有假装自己是完整系统。它明确不接后端、不接数据库、不含鉴权,这反而让项目目标更干净。

后续可以怎么扩展

如果要把它从前端演示推进成真正的审核系统,可以继续补:

  • 流程模板保存、发布和版本管理。
  • 审批实例运行时引擎。
  • 用户、角色、部门和权限体系。
  • 条件分支表达式校验。
  • 待办任务流转、催办和超时策略。
  • 审批记录、审计日志和附件存储。
  • 流程 JSON 的导入、回滚和 diff。

但无论后端怎么加,前端这条边界都值得保留:用户在画布上编排节点和连线,系统把它导出为结构化流程数据。

有了这个边界,审批系统才不会只是几张静态表单,而是能逐步长成真正可配置的流程平台。

最后更新:2025-11-18