当前位置: 首页 > news >正文

Vue仿钉钉审批流程:从零搭建可视化工作流引擎

1. 为什么需要可视化审批流程

最近在做一个企业内部管理系统,客户明确提出要仿照钉钉的审批流程功能。刚开始我觉得这有什么难的,不就是几个表单提交吗?真正动手做的时候才发现,钉钉的审批流设计确实精妙。比如部门经理审批后自动流转到财务,金额超过1万需要总经理签字,这些规则配置起来非常灵活。

传统审批流程的代码通常硬编码在系统里,每次业务规则变更都需要开发人员修改代码。而可视化工作流引擎允许非技术人员通过拖拽方式配置流程,就像搭积木一样简单。我见过最夸张的例子是某公司HR小姐姐自己配置了20多种请假审批流程,完全没麻烦技术部门。

用Vue来实现这类功能特别合适,它的响应式特性和组件化开发模式,能让我们快速构建可交互的节点元素。下面这个最简单的审批流示例,包含开始、审批人和结束三个节点:

<template> <div class="workflow-container"> <StartNode /> <ApproverNode :approvers="['张三','李四']" /> <EndNode /> </div> </template>

2. 项目初始化与基础结构搭建

2.1 创建Vue项目与安装依赖

建议使用Vue CLI脚手架初始化项目,我习惯用Vite因为它启动速度更快。必须安装的依赖有:

  • vuedraggable:实现节点拖拽功能的核心库
  • element-ui:采用它的弹窗和表单组件
  • jsplumb:连接线的绘制工具
npm create vite@latest workflow-engine --template vue cd workflow-engine npm install vuedraggable element-plus jsplumb

2.2 设计页面布局结构

参考钉钉的界面,我把工作区划分为三个区域:

  1. 左侧面板:存放各种节点类型的组件
  2. 中间画布:拖拽编排流程的主要区域
  3. 右侧配置面板:点击节点时显示详细设置

关键CSS技巧是给画布容器设置transform-origin: 0 0配合缩放控制,这样放大缩小时所有元素能保持一致比例。下面是核心布局代码:

<div class="designer-container"> <div class="node-panel"> <NodeItem v-for="item in nodeTypes" :type="item.type" /> </div> <div class="flow-canvas" ref="canvas"> <Draggable v-model="nodes" @end="onDragEnd"> <TransitionGroup> <NodeWrapper v-for="node in nodes" :node="node" /> </TransitionGroup> </Draggable> </div> <div class="config-panel" v-if="selectedNode"> <NodeConfig :node="selectedNode" /> </div> </div>

3. 核心功能实现细节

3.1 实现节点拖拽与连线

拖拽功能用vuedraggable实现起来特别简单,但有几个坑我踩过:

  • 需要给拖拽容器设置group属性区分来源
  • 拖拽结束时需要计算在画布上的准确位置
  • jsplumb连线时要等DOM渲染完成

节点连线的核心代码:

import { jsPlumb } from 'jsplumb' export default { mounted() { this.jsPlumb = jsPlumb.getInstance() this.jsPlumb.ready(() => { this.jsPlumb.setContainer(this.$refs.canvas) // 设置连线样式 this.jsPlumb.importDefaults({ Connector: ['Flowchart', { stub: 20 }], PaintStyle: { strokeWidth: 2 } }) }) }, methods: { connectNodes(sourceId, targetId) { this.jsPlumb.connect({ source: sourceId, target: targetId, anchors: ['Bottom', 'Top'] }) } } }

3.2 审批人设置模块开发

钉钉最实用的功能是可以按组织架构选择审批人,我们简化实现如下功能:

  • 指定具体人员
  • 按角色选择(如部门主管)
  • 连续多级审批

用Element UI的Tree组件展示组织架构:

<el-tree :data="deptTree" show-checkbox node-key="id" :props="{label: 'name'}" @check-change="handleCheckChange" />

后台需要返回这样的树形数据:

[ { "id": 1, "name": "研发部", "children": [ {"id": 101, "name": "前端组", "type": "dept"}, {"id": 102, "name": "后端组", "type": "dept"} ] } ]

4. 条件分支与流程控制

4.1 实现条件分支逻辑

钉钉的条件分支可以基于表单字段值进行路由判断,比如:

  • 请假类型为年假 → 人事备案
  • 金额大于5000 → 财务审核

我们通过动态渲染条件表单来实现:

<template v-if="node.type === 'condition'"> <el-form> <el-form-item label="条件名称"> <el-input v-model="node.name" /> </el-form-item> <el-form-item label="判断字段"> <el-select v-model="node.field"> <el-option v-for="field in formFields" :label="field.label" :value="field.prop" /> </el-select> </el-form-item> <el-form-item label="比较方式"> <el-select v-model="node.operator"> <el-option value=">" label="大于" /> <el-option value="<" label="小于" /> </el-select> </el-form-item> </el-form> </template>

4.2 流程校验与保存

在保存前需要做这些验证:

  1. 所有审批节点必须设置审批人
  2. 条件分支必须有默认路由
  3. 不能存在孤立节点

校验通过后生成的流程数据格式示例:

{ "nodes": [ { "id": "node1", "type": "approver", "approvers": ["user1", "user2"], "position": { "x": 100, "y": 50 } } ], "edges": [ { "source": "node1", "target": "node2", "condition": "amount > 5000" } ] }

5. 性能优化与实践建议

5.1 大型流程的性能问题

当节点超过50个时,我遇到过这些性能瓶颈:

  • jsPlumb连线渲染卡顿
  • Vue响应式数据更新变慢
  • 缩放操作不流畅

优化方案:

  1. 使用v-memo缓存静态节点
  2. 对jsPlumb采用批量渲染
  3. 缩放时隐藏连线
const onZoom = (scale) => { this.jsPlumb.setSuspendDrawing(true) this.scale = scale this.$nextTick(() => { this.jsPlumb.setSuspendDrawing(false) }) }

5.2 与后端交互的注意事项

前后端协作时容易出问题的地方:

  • 节点ID生成策略(建议前端生成UUID)
  • 位置信息保存比例而非绝对值
  • 版本控制机制

推荐的后端接口设计:

// 保存流程 POST /api/workflow/:id { "name": "请假审批", "nodes": [...], "edges": [...], "version": "2023-08-20" } // 获取流程 GET /api/workflow/:id/version/:version

6. 扩展功能开发思路

6.1 抄送与通知功能

除了审批节点,还可以实现:

  • 邮件通知抄送人
  • 企业微信消息推送
  • 审批超时提醒

通知配置组件示例:

<el-form-item label="通知方式"> <el-checkbox-group v-model="notifyTypes"> <el-checkbox label="email">邮件</el-checkbox> <el-checkbox label="sms">短信</el-checkbox> </el-checkbox-group> </el-form-item>

6.2 移动端适配方案

为了让流程在手机上也能配置,需要:

  1. 简化拖拽操作(改为点击添加)
  2. 优化连线显示方式
  3. 使用手势缩放

媒体查询示例:

@media (max-width: 768px) { .node { width: 80px; padding: 5px; } .node-config { position: fixed; top: 0; width: 100%; } }

这个项目从零开始搭建用了两周时间,最复杂的部分是条件分支的逻辑处理。建议先用简单的直线流程跑通核心功能,再逐步添加高级特性。如果遇到jsPlumb连线异常的问题,记住一定要在DOM更新完成后调用repaintEverything方法。

http://www.cnnetsun.cn/news/1957045.html

相关文章:

  • JMeter全自动阶梯压力测试流程(使用普通线程组)
  • FDTD进阶指南:Lumerical脚本精讲之仿真区域与网格优化(四)
  • 如何高效管理Windows右键菜单:ContextMenuManager专业指南
  • Pixel Dimension Fissioner 企业级CI/CD流水线设计:从代码到部署
  • MiniCPM-V-2_6优化指南:提升推理速度,降低内存占用
  • XUnity自动翻译器:5分钟打造你的专属中文游戏世界
  • Cursor Rules 概念、编写与接入指南
  • 动手学深度学习(二十八)——微调实战:从理论到高效调参
  • 零代码基础:用Retinaface+CurricularFace镜像快速实现人脸相似度计算
  • Qwen3-0.6B-FP8高算力适配:RTX 4090D上FP8推理性能优化教程
  • 用于显示器防眩光面板的板材有哪些尺寸?采购前必须确认这几点
  • 基于logcat日志查找卡顿
  • 万象视界灵坛环境部署:OpenShift平台容器化部署与RBAC权限控制
  • Element-UI表单进阶:精准校验单个与多个字段的实战指南
  • 深入Transformer架构:利用Mirage Flow解析与可视化模型注意力机制
  • C语言存在的问题及Zig语言如何改进,差异对比全在这
  • 6 文件保存功能优化
  • 解读核心Maintainer观点|Presto 不只是版本升级!从查询引擎到湖仓执行层,AI Infra 新方向
  • 解析CSV文件处理中的常见问题与解决方案
  • 为什么你的浏览器下载需要Motrix WebExtension?终极效率提升指南
  • Visual C++运行库终极解决方案:三步告别DLL缺失烦恼
  • 通义千问2.5-7B-Instruct新手入门:无需代码基础搭建智能对话系统
  • S2-Pro大模型VMware虚拟机Ubuntu环境配置一站式指南
  • Wan2.2-I2V-A14B开发者指南:基于API封装私有视频生成SaaS服务
  • Qwen3.5-9B零基础部署:5分钟本地跑通,笔记本也能玩转原生多模态
  • Pixel Epic · Wisdom Terminal 物联网(IoT)后端开发:处理海量传感器数据的智能分析平台
  • 写HTML就能出视频?HyperFrames安装使用教程及资源分享
  • Pixel Couplet Gen惊艳案例:海外华人社区用Pixel Couplet Gen传播春节文化
  • Golang go mod vendor怎么用_Golang vendor教程【必备】
  • Z-Image Turbo实战指南:4步生成高清图像全流程