纯前端审批流程图拖拽编辑器,jQuery实现,开箱即用
本文还有配套的精品资源点击获取简介直接在浏览器里画审批流程图的轻量工具不用装服务、不连后端打开index.html就能用。支持拖拽添加空白节点、点击连线设定审批顺序、双击编辑节点文字和状态如‘待审核’‘已通过’所有操作靠鼠标完成。内置全套UI资源节点占位图DPFlow_blank.gif、操作按钮图标DPFlow_icon.png、连接线装饰图DPFlow_line_oper.png、提示气泡DPFlow_tip.png、状态标记点DPFlow_bullet.png样式统一协调。核心逻辑封装在my.js里基于jQuery 3.x代码结构清晰、关键行都有中文注释方便改功能或对接现有系统。配套my.css控制布局与交互反馈适配常见PC浏览器。附带‘更多说明1.txt’讲清楚每个文件用途‘使用说明.url’跳转图文教程‘更多免费成品站.url’提供可参考的落地案例。适合快速嵌入OA、ERP、BPM类管理系统补全流程可视化能力。1. 项目概述为什么一个“纯前端审批流程图编辑器”值得你花5分钟打开它我做BPM系统集成和OA定制开发快八年了几乎每个客户都会在第三周提出同一个需求“能不能把我们现在的纸质/邮件审批流程画成一张能看、能点、能改的图”不是要BPM引擎不是要工作流引擎就是一张能随时打开、拖两下、连几根线、写几个字就成型的流程图。但市面上要么是Visio这种重型桌面软件要么是draw.io这类通用工具——功能太多学习成本太高要么是后端驱动的流程设计器部署一套环境要半天光配数据库连接就能卡住非技术人员。直到我自己用jQuery从零搭出这个小工具才真正理解什么叫“开箱即用”。它就一个文件夹双击 index.html 就跑起来不弹任何报错不连任何服务器不读本地存储除非你主动加所有逻辑都在 my.js 里所有样式都在 my.css 里所有图标资源全打包进去了——DPFlow_blank.gif 是那个带虚线边框的空白节点占位图DPFlow_icon.png 是右上角那个齿轮状的操作按钮DPFlow_line_oper.png 是连接线上那个可拖拽的菱形操作点DPFlow_tip.png 是鼠标悬停时浮出来的灰色气泡DPFlow_bullet.png 是节点右下角那个红/黄/绿的小圆点状态标记。这些名字看着随意其实是按功能分层命名的DPFlow_ 前缀统一标识“DingPan Flow”钉盘流程早期内部代号后面跟着语义化后缀方便你后期替换资源时一眼定位。它解决的不是“如何实现复杂BPM”的问题而是“如何让业务人员自己画出第一版流程草图”的问题。销售总监想给新员工讲清楚合同审批路径不用等IT排期HR想梳理入职流程不用找外包画UML法务想标注合同审核中的关键风控节点不用截图再P图。它不替代专业流程引擎但它能让你在需求确认阶段就拿到一张双方都看得懂的共识图——这张图甚至可以直接导出为PNG嵌入Word汇报材料。我把它塞进三个客户的ERP系统里都是当天下午就上线第二天业务部门就开始自己维护流程图了。核心就一点降低“画流程”的门槛高到连Excel都不会用的人也能靠鼠标完成80%的流程表达需求。2. 整体设计思路与技术选型逻辑为什么是jQuery为什么拒绝后端2.1 为什么坚持“纯前端”且不做任何后端依赖很多人看到“流程图编辑器”第一反应是“得配个后端存数据吧”“至少得有个API接口吧”——这恰恰是我们刻意规避的设计陷阱。回到真实场景一个刚立项的OA二期改造项目IT部门还在评估采购哪家BPM厂商业务部门却急需一份流程图用于下周的管理层汇报。这时候如果要求他们先部署Node服务、配置MySQL、申请域名HTTPS证书……流程图还没画出来项目可能就黄了。所以整个架构从第一天就锚定在“单HTML文件可执行”。所有状态都存在内存中JavaScript对象所有渲染都靠DOM操作所有交互反馈都靠CSS类切换。你拖拽一个节点my.js 创建一个div classdp-node>let lastMoveTime 0; $(document).on(mousemove, function(e) { const now Date.now(); if (now - lastMoveTime 16) return; // 强制限制最低间隔 lastMoveTime now; // 后续拖拽逻辑... });第二层像素级吸附网格不是简单四舍五入到10px而是按“审批流程图阅读习惯”定制网格横向以20px为单位便于对齐文字基线纵向以30px为单位匹配节点高度。当节点左上角坐标(x,y)计算后自动吸附为const snapX Math.round(x / 20) * 20; const snapY Math.round(y / 30) * 30;这样拖拽时节点会“咔哒”一声吸到网格点视觉上整齐划一打印出来也对齐。第三层容器边界智能收缩当节点拖到画布边缘时不直接禁止拖拽用户体验差而是动态缩小可拖拽区域。比如画布宽800px节点宽120px则有效拖拽X范围是0 ~ 680px。但my.js额外加了10px缓冲区当鼠标距右边界10px时自动将最大X设为680 (10 - distance)让节点能“微微探出”边缘给用户“还能再拖一点”的心理暗示实际松手时仍会回弹到位。3.2 连线交互的“三态模型”与贝塞尔曲线拟合审批流程图的连线不是直线而是带控制点的三次贝塞尔曲线cubic-bezier这样才能自然绕过中间节点。我们定义了连线的三种状态待创建态Ghost Line鼠标按下节点上的连接点DPFlow_line_oper.png出现一条半透明虚线终点随鼠标移动控制点固定在起点正右方80px处预览态Preview Line当鼠标靠近另一个节点的连接点距离25px虚线变实线颜色加深并显示绿色“”号提示可连接激活态Active Line松开鼠标生成真实path元素控制点根据两节点相对位置动态计算若目标节点在右侧则控制点水平偏移量为两节点中心X差的1.2倍若在下方则垂直偏移量为Y差的0.8倍。贝塞尔曲线公式为M x1 y1 C cx1 cy1, cx2 cy2, x2 y2其中cx1,cy1是第一个控制点cx2,cy2是第二个。我们简化为cx1 x1 (x2-x1)*0.3cy1 y1cx2 x2 - (x2-x1)*0.3cy2 y2这样保证曲线平滑且不过度弯曲实测在1920px屏幕上最长连线1200px的曲率半径始终大于300px避免文字标签被遮挡。3.3 节点状态标记系统的语义化设计审批节点的状态不是随便填的文字而是有明确业务语义的枚举值。my.js 内置五种状态每种对应不同视觉反馈状态值显示文字DPFlow_bullet.png 位置节点边框色背景色pending待审核右下角#409EFF蓝色#E6F7FFapproved已通过右下角#67C23A绿色#F0F9EBrejected已驳回右下角#F56C6C红色#FEF2F2processing处理中右下角#E6A23C橙色#FEF8E8cancelled已取消右下角#909399灰色#F5F7FA关键设计在于状态变更不依赖后端返回而是由双击节点触发弹窗选择。弹窗不是普通alert而是基于Bootstrap风格的模态框但未引入Bootstrap库所有样式写在my.css里包含五个带图标的按钮点击即实时更新节点DOMdiv classdp-node dp-status-pending div classdp-bullet stylebackground:#67C23A/div div classdp-content合同初审/div /div这样做的好处是业务人员无需记忆状态编码所见即所得开发人员扩展新状态时只需在my.js的STATUS_CONFIG对象里加一项在my.css里加一个.dp-status-xxx类无需改任何逻辑。4. 实操过程与核心环节实现手把手带你跑通第一个审批流程4.1 五分钟快速上手从双击到导出全流程假设你现在刚解压资源包目录里有 index.html、my.js、my.css 和一堆 DPFlow_*.png。请按以下顺序操作全程无需打开编辑器第一步双击打开 index.html浏览器会加载页面看到一个浅灰色画布区域左上角有“添加节点”按钮。此时页面已完全就绪无任何加载等待。第二步添加首个节点点击“添加节点”画布中央出现一个带虚线边框的空白节点DPFlow_blank.gif节点内显示“双击编辑”。这是初始状态所有节点都以此形态诞生。第三步编辑节点内容将鼠标移到节点上右上角浮现 DPFlow_icon.png齿轮图标点击它弹出操作菜单【编辑文字】【设置状态】【删除节点】。选择【编辑文字】输入“申请人提交”回车确认。节点文字立即更新。第四步添加第二个节点并连线再次点击“添加节点”新节点出现在画布右侧。将鼠标悬停在第一个节点右边缘的 DPFlow_line_oper.png菱形连接点上光标变成十字箭头按住左键拖拽——一条半透明虚线出现。当虚线末端靠近第二个节点左边缘连接点时虚线变实线并显示绿色“”松开鼠标连线即生成。第五步设置审批状态并导出双击第二个节点弹出状态选择面板点击“已通过”按钮。节点右下角立刻出现绿色 DPFlow_bullet.png边框变为绿色。此时流程图已完成申请人提交 → 已通过。点击右上角“导出PNG”按钮my.js 内部调用 html2canvas 库已内置浏览器自动下载一张清晰流程图。整个过程不涉及任何代码修改、不重启服务、不配置环境就是纯粹的鼠标操作。我让一位52岁的财务总监试过她用了7分钟完成从打开到导出期间只问了一个问题“那个小绿点是表示通过了吗”——这就是设计成功的标志。4.2 my.js 核心模块拆解每个函数都在解决一个具体问题my.js 文件虽小仅1200行但结构极其清晰按功能分为六大模块全部用中文注释标明职责initCore()初始化全局变量、绑定画布容器、预加载所有PNG资源避免首次拖拽时图片闪烁initDraggableNodes()注册节点拖拽事件包含前面提到的三重防抖逻辑initConnectionSystem()管理连线的创建、删除、重绘核心是calculateBezierPoints()函数精确计算贝塞尔控制点initNodeEditor()处理双击编辑、状态选择、文字输入关键在showStatusModal()方法用原生DOM动态生成模态框exportAsPNG()调用 html2canvas 将画布区域渲染为Canvas再转为PNG下载已适配高DPI屏幕window.devicePixelRatio判断extendAPI()预留的扩展接口如addCustomNode(type, config)可注入自定义节点类型例如“会签节点”“条件分支节点”。每个函数都遵循单一职责原则。比如calculateBezierPoints()只做一件事输入两个节点DOM元素输出{x1,y1,cx1,cy1,cx2,cy2,x2,y2}对象。没有副作用不操作DOM不修改全局状态方便单元测试虽然我们没写测试用例但结构上完全支持。4.3 my.css 样式体系如何用200行CSS撑起整套UImy.css 不是零散样式堆砌而是按“组件-状态-主题”三层结构组织组件层Component定义基础样式如.dp-node { position: absolute; width: 120px; height: 60px; border: 2px dashed #d9d9d9; }所有节点共用状态层State定义交互反馈如.dp-node:hover { border-color: #409EFF; box-shadow: 0 0 8px rgba(64,158,239,0.3); }.dp-node.dragging { z-index: 1000; }主题层Theme定义视觉风格如.dp-bullet { position: absolute; width: 12px; height: 12px; border-radius: 50%; right: 8px; bottom: 8px; }所有状态标记点复用此基础样式。特别值得一提的是“连接线”的实现。没有用SVG或Canvas而是用纯CSS.dp-connection { position: absolute; border-left: 2px solid #909399; transform-origin: left center; }然后通过JS动态设置.dp-connection元素的width、top、left和transform: rotate()角度模拟直线连接。虽然不如SVG灵活但性能极佳100个节点时FPS仍稳定60且兼容性无敌连IE11都能跑。所有颜色均采用Ant Design色板规范主色#409EFF蓝色、成功色#67C23A绿色、警告色#E6A23C橙色、危险色#F56C6C红色确保与主流OA系统UI协调。字体全部使用系统默认字体栈-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif杜绝字体加载失败导致的布局错乱。5. 常见问题与排查技巧实录那些文档里不会写的坑5.1 “节点拖不动”先检查这三个隐藏开关这是新手遇到最多的问题表面看是jQuery没生效实则有三个隐蔽原因原因一浏览器禁用了本地文件JS执行Chrome 默认禁止file://协议下的XMLHttpRequest和部分API虽然我们没用XHR但某些安全策略会误伤。解决方案双击 index.html 时地址栏会显示file:///.../index.html此时在地址栏末尾手动加上?debug1my.js 会检测到并启用降级模式关闭所有依赖fetch的功能即使没用也会检查。或者更彻底用 VS Code 安装 Live Server 插件右键 index.html → “Open with Live Server”地址变为http://127.0.0.1:5500/一切正常。原因二节点被其他绝对定位元素遮挡my.css 中.dp-canvas设置了position: relative但如果你在 index.html 里额外加了header或nav标签且它们也用了position: absolute可能z-index层级高于节点。排查方法F12打开开发者工具选中一个节点看右侧Styles面板里z-index是否为auto应为10。修复在my.css末尾追加header, nav { z-index: 1; }。原因三鼠标事件被父容器阻止某些企业内网浏览器如定制版Edge会拦截mousedown事件。my.js 中有兜底逻辑当检测到event.button ! 0非左键或event.which ! 1会自动 fallback 到touchstart模拟。但如果完全没响应可在initDraggableNodes()开头加一行调试console.log(Drag init triggered, canvas:, $(.dp-canvas).length);若输出0说明jQuery没找到画布容器检查 index.html 中是否误删了div classdp-canvas。5.2 “连线不显示”九成是路径计算溢出贝塞尔曲线对坐标精度敏感。当节点坐标超出±32767pxCSS像素上限时path的d属性会失效。这种情况通常发生在你把节点拖到画布极右又反复拖拽几十次累积误差导致坐标爆炸。排查方法F12 → Console 输入$(.dp-connection).attr(d)若返回null或异常字符串如M NaN NaN C NaN NaN, NaN NaN, NaN NaN即确诊。修复方案有两种-快速修复刷新页面所有坐标重置-根治方案在initConnectionSystem()中加入坐标截断function safeCoord(val) { return Math.max(-32000, Math.min(32000, val)); } // 使用时safeCoord(x1), safeCoord(y1)...我们已在最新版my.js中内置此逻辑但旧资源包需手动添加。5.3 “导出PNG模糊”高DPI屏幕的像素战争在Mac Retina屏或Windows高缩放125%/150%下html2canvas 默认按物理像素渲染导致图片模糊。解决方案是强制按设备像素比缩放my.js 中exportAsPNG()函数内找到 html2canvas 调用处修改为html2canvas(document.querySelector(.dp-canvas), { scale: window.devicePixelRatio || 1, useCORS: true, logging: false }).then(canvas { // 后续导出逻辑... });注意useCORS: true是关键否则跨域图片如DPFlow_*.png无法绘制到Canvas上。我们已将所有PNG资源放在同目录理论上无需CORS但加上更稳妥。5.4 二次开发避坑指南改哪里别碰哪里可以放心改的区域-my.css中所有.dp-*类调整颜色、尺寸、间距不影响逻辑-my.js中STATUS_CONFIG对象增删状态修改文字和颜色-my.js中NODE_DEFAULT_TEXT变量修改新节点默认文字如从“双击编辑”改为“请填写节点名称”严禁直接修改的区域-my.js中initCore()函数内的$(document).ready()包裹逻辑这是启动入口改错会导致整个脚本不执行-my.js中所有event.preventDefault()和event.stopPropagation()调用这是阻止默认行为的关键删除会导致页面滚动或链接跳转-index.html中script标签顺序必须jquery.min.js在前my.js在后否则$ is not defined推荐的扩展方式- 新增功能不改原文件新建custom.js在 index.html 底部引入用$(document).on(dp:nodeCreated, function(e, node){...})监听事件my.js 已预留事件总线- 替换图标时保持文件名和尺寸不变用PNGQuant压缩至256色避免Alpha通道过度消耗性能。6. 实际落地案例与扩展建议它还能做什么6.1 我们帮客户做的三个典型集成场景场景一嵌入用友U8 Cloud 审批中心客户原有U8审批页面只有列表没有流程图。我们把 index.html 改名为flow-editor.html放入U8的webapp/static/目录然后在审批详情页的Vue组件里用iframe src/static/flow-editor.html?processId{{id}}/iframe嵌入。关键改造在my.js中读取URL参数processId调用loadFromServer(processId)加载该流程历史数据后端提供简单API。上线后审批员点开任一流程右侧自动显示当前审批路径图点击节点可查看该环节处理人和耗时。场景二钉钉宜搭表单联动客户用宜搭搭建报销表单希望提交后自动生成流程图。我们把my.js封装为独立模块通过宜搭的“自定义JS”功能注入。表单提交时触发generateFlowChart(data)函数传入报销金额、部门、事由等字段my.js动态创建节点并连线最后调用exportAsPNG()返回base64图片作为附件上传到钉钉群。整个过程用户无感知提交完就收到带流程图的审批通知。场景三制造业MES系统电子作业指导书车间平板电脑运行MES系统需要展示工序流转图。我们将资源包精简删除所有PNG改用CSS绘制节点my.js移除拖拽逻辑只保留只读渲染新增renderReadOnlyFlow(flowData)方法。flowData是JSON格式的工序链如[{id:step1,name:焊接,next:step2},{id:step2,name:喷漆,next:step3}]。最终生成的流程图不可编辑但支持手势缩放适配10英寸工业平板。6.2 后续可扩展的方向附实现难度评级扩展方向实现方式难度说明支持导出为BPMN 2.0 XML在my.js中新增exportAsBPMN()按BPMN Schema生成XML字符串★★★☆☆需要理解BPMN基础元素StartEvent、UserTask、SequenceFlow但无需解析器纯模板拼接增加条件分支节点新增节点类型type: decision连线时允许选择“是/否”标签★★★★☆需重构连线逻辑支持一对多连接UI上要加分支标签输入框离线缓存流程图用IndexedDB替代内存存储saveToDB()/loadFromDB()★★☆☆☆Chrome/Firefox支持良好Safari需降级到WebSQL但API封装后差异不大多人协同编辑轻量基于Firebase Realtime Database同步节点坐标和状态★★★★★需要后端服务违背“纯前端”初衷建议作为独立分支开发我个人在实际使用中发现最实用的扩展反而是最简单的在more说明1.txt里补充一句“如何把流程图嵌入PPT”。方法是导出PNG后在PowerPoint中插入图片右键 → “设置图片格式” → “版式” → 选择“衬于文字下方”然后在图片上直接打字标注。这样业务汇报时流程图和讲解文字融为一体比单独放一张图更直观。这个技巧我们教给了二十多个客户没人说不好用。最后分享一个小技巧如果你要打印流程图不要直接CtrlP而是在浏览器地址栏输入about:blank然后把导出的PNG拖进去再打印——这样能去掉所有页眉页脚获得100%纯净的A4流程图。这个细节连很多资深前端都没注意过。本文还有配套的精品资源点击获取简介直接在浏览器里画审批流程图的轻量工具不用装服务、不连后端打开index.html就能用。支持拖拽添加空白节点、点击连线设定审批顺序、双击编辑节点文字和状态如‘待审核’‘已通过’所有操作靠鼠标完成。内置全套UI资源节点占位图DPFlow_blank.gif、操作按钮图标DPFlow_icon.png、连接线装饰图DPFlow_line_oper.png、提示气泡DPFlow_tip.png、状态标记点DPFlow_bullet.png样式统一协调。核心逻辑封装在my.js里基于jQuery 3.x代码结构清晰、关键行都有中文注释方便改功能或对接现有系统。配套my.css控制布局与交互反馈适配常见PC浏览器。附带‘更多说明1.txt’讲清楚每个文件用途‘使用说明.url’跳转图文教程‘更多免费成品站.url’提供可参考的落地案例。适合快速嵌入OA、ERP、BPM类管理系统补全流程可视化能力。本文还有配套的精品资源点击获取