简介这是一套可直接二次开发的OA办公自动化系统源码面向需要搭建或改造企业内部审批流程的开发者与团队。资源以C#与ASP.NET技术栈实现涵盖Web端与移动端两套界面核心模块包括业务逻辑层、数据库工具类库与公共组件便于研究审批流程的规则设计与落地方式。压缩包共约2000个文件43.54MB以gif、cs、aspx、png、jpg、js为主另有dll、doc、css、html及数据库文件等分别对应界面素材、后端代码、页面逻辑、样式脚本与数据存储。其中业务逻辑层集中处理审批规则数据库工具类负责连接与数据操作公共模块提供可复用方法移动端目录支持随时审批。目前已有6931人学习下载适合希望快速理解OA架构、掌握审批流程实现并完成定制化改造的中高级开发者参考借鉴。1. 从一张请假单说起这套 OA 源码到底能跑出什么很多团队做内部审批最开始都是拿在线表格凑合填表、发链接、等人点、手动催。流程一多表格就变成黑匣子谁卡在哪个节点全靠问。这套 OA 系统源码解决的就是这个问题——它把审批流程做成可配置的引擎请假、报销、采购、用章都能自己画流程图节点上挂审批人、条件分支、抄送人发起后自动流转每一步留痕。技术栈是典型的 Java 后端加前端管理台数据库用 MySQL流程引擎常见做法是集成 Activiti 或 Flowable权限模型走 RBAC。适合两类人一类是公司内部想自建办公自动化的开发者另一类是拿它当流程引擎学习案例的学生或转行者。源码完整能直接部署也能按业务改流程定义。2. 架构与目录先看清模块边界再动手2.1 整体分层与请求链路这套 OA 的代码结构是标准的前后端分离加分层架构。后端按 Controller、Service、Mapper 三层组织流程引擎单独抽一层避免业务代码和流程 API 搅在一起。前端是管理台加表单设计器管理台负责用户、角色、菜单、流程模型表单设计器负责拖拽生成业务表单。一次审批请求的链路大致是前端提交表单数据 → Controller 接收 → Service 校验业务规则 → 调用流程引擎启动实例 → 引擎按流程图推进 → 每个节点写入审批记录 → 返回当前节点状态。常见做法是把流程定义文件BPMN 2.0 的 XML放在 resources 目录下部署时由引擎自动加载。这样改流程不用改 Java 代码重新部署流程定义即可。目录结构上我一般会这样分oa-system/ ├── oa-common/ 公共模块工具类、常量、统一返回 ├── oa-model/ 实体与 DTO ├── oa-mapper/ 数据库访问层 ├── oa-service/ 业务逻辑 ├── oa-flow/ 流程引擎封装 ├── oa-web/ Controller 与启动类 └── oa-ui/ 前端管理台这个分法的好处是流程引擎的依赖只在 oa-flow 里出现其他模块不直接碰引擎 API。二次开发时想换引擎只动一个模块。2.2 流程引擎的接入方式流程引擎接入有两种常见姿势一种是把引擎的 Service 直接注入业务 Service另一种是包一层自己的 FlowService对外只暴露 start、complete、reject、query 四个方法。这套源码用的是后者好处是业务代码不依赖具体引擎类测试时也好 mock。Service public class FlowService { Autowired private RuntimeService runtimeService; // 引擎运行时服务 Autowired private TaskService taskService; // 任务服务 // 启动流程实例businessKey 关联业务单据 public String startFlow(String processKey, String businessKey, MapString, Object vars) { ProcessInstance instance runtimeService.startProcessInstanceByKey( processKey, businessKey, vars); return instance.getId(); } // 完成任务并推进到下一节点 public void complete(String taskId, MapString, Object vars) { taskService.complete(taskId, vars); } }processKey是流程定义的唯一标识和 BPMN 文件里的 id 对应businessKey是业务单据主键用来把流程实例和业务数据关联起来查审批历史时靠它反查vars是流程变量条件分支判断就靠它。参数传错最常见的后果是流程启动后找不到业务数据或者分支条件永远走 false。2.3 权限模型与菜单加载权限走的是用户、角色、菜单三张表加两张关联表。用户挂角色角色挂菜单和按钮权限。登录后前端拿菜单树渲染侧边栏后端接口用注解校验权限。这套模型不新鲜但源码里把数据权限也做了不同角色能看到不同部门的单据。实现方式是在 Mapper 的查询里拼部门条件而不是在 Java 里过滤避免数据量大时内存爆掉。3. 跑起来从建库到发起第一笔审批3.1 环境准备与数据库初始化跑这个项目需要 JDK 8 或 11、Maven、MySQL 5.7 以上、Node.js 14 以上。先把数据库建好字符集用 utf8mb4否则中文和表情会乱码。源码的 sql 目录下一般有建表脚本和初始数据脚本按顺序执行。# 建库 mysql -u root -p -e CREATE DATABASE oa_system DEFAULT CHARSET utf8mb4; # 导入表结构和初始数据 mysql -u root -p oa_system sql/schema.sql mysql -u root -p oa_system sql/data.sqlschema.sql建表data.sql插初始用户、角色、菜单和一条示例流程定义。执行完检查一下用户表有没有数据没有的话登录会一直提示账号密码错误这是新手第一个坑。3.2 后端配置与启动改application.yml里的数据库连接、Redis 连接如果有缓存、文件上传路径。流程引擎的配置一般在单独的文件里指定数据库类型和是否自动建表。如果 schema.sql 已经建了引擎表就把自动建表关掉否则启动时会报表已存在。spring: datasource: url: jdbc:mysql://localhost:3306/oa_system?useUnicodetruecharacterEncodingutf8 username: root password: 你的密码 # 流程引擎配置 activiti: database-schema-update: none # 已手动建表关闭自动更新 async-executor-activate: false # 开发环境关掉异步任务database-schema-update设成 none 是防止引擎启动时改表结构async-executor-activate关掉是避免开发时定时任务干扰调试。启动类跑起来后控制台看到 Tomcat 端口和启动耗时就算成功。3.3 前端启动与联调前端进 oa-ui 目录先装依赖再启动。开发环境一般配了代理把 /api 转发到后端端口。cd oa-ui npm install npm run dev启动后浏览器打开控制台地址用初始账号登录。如果接口 404检查代理配置里的 target 是不是后端实际端口如果跨域报错检查后端有没有开 CORS 或者代理有没有生效。登录进去后先看菜单能不能加载菜单空的话多半是角色没关联菜单。3.4 发起一笔请假审批登录后进流程中心选请假流程填表单提交。提交后流程实例启动当前节点出现在待办列表里。用审批人账号登录打开待办点同意流程走到下一节点。整个过程在审批记录里能看到时间、操作人、意见。这一步跑通说明引擎、权限、表单三块都正常。跑不通就按顺序查流程定义有没有部署、表单字段和流程变量对不对得上、审批人有没有配。4. 核心模块拆解流程定义、表单绑定与审批记录4.1 流程定义与 BPMN 文件流程定义就是一张图用 BPMN 2.0 的 XML 描述。节点类型常见的有开始事件、用户任务、排他网关、结束事件。用户任务上挂审批人排他网关上挂条件表达式。下面是一个简化后的请假流程片段process idleaveFlow name请假审批 startEvent idstart/ userTask iddeptLeader name部门审批 activiti:assignee${deptLeader}/ exclusiveGateway iddayCheck/ sequenceFlow sourceRefdeptLeader targetRefdayCheck/ sequenceFlow sourceRefdayCheck targetRefhrAudit conditionExpression xsi:typetFormalExpression ${days 3} /conditionExpression /sequenceFlow userTask idhrAudit name人事审批 activiti:assignee${hrUser}/ endEvent idend/ /processid是流程唯一标识启动时用assignee里的${deptLeader}是流程变量启动时传进去conditionExpression里的${days 3}决定超过三天才走人事审批。改流程就是改这个文件改完重新部署。注意变量名要和启动时传的 key 完全一致大小写错了条件永远不成立。4.2 表单与流程变量绑定表单设计器生成的字段提交时要转成流程变量。常见做法是前端提交 JSON后端把 JSON 里的字段平铺成 Map 传给引擎。字段名和 BPMN 里的变量名要对应否则条件分支拿不到值。// 表单数据转流程变量 public MapString, Object buildVars(LeaveForm form) { MapString, Object vars new HashMap(); vars.put(days, form.getDays()); // 请假天数条件分支用 vars.put(deptLeader, form.getDeptLeader()); // 部门审批人 vars.put(hrUser, form.getHrUser()); // 人事审批人 vars.put(reason, form.getReason()); // 请假原因仅记录 return vars; }days是数值型条件表达式里直接比较审批人变量是字符串对应用户账号。如果表单字段是日期要转成引擎能识别的类型直接传字符串在部分引擎版本里会报类型转换错误。4.3 审批记录与历史查询每完成一个任务引擎会往历史表写一条记录。查审批历史一般查act_hi_taskinst和act_hi_comment两张表前者是任务实例后者是审批意见。业务侧再包一层接口把历史记录和业务单据拼在一起返回。// 查询某单据的审批历史 public ListAuditRecord queryHistory(String businessKey) { HistoricProcessInstance instance historyService .createHistoricProcessInstanceQuery() .processInstanceBusinessKey(businessKey) .singleResult(); return historyService.createHistoricTaskInstanceQuery() .processInstanceId(instance.getId()) .orderByHistoricTaskInstanceEndTime().asc() .list() .stream() .map(this::toRecord) .collect(Collectors.toList()); }businessKey是业务单据主键查历史必须靠它orderByHistoricTaskInstanceEndTime().asc()保证记录按时间正序前端展示才符合阅读习惯。如果查不到记录先确认流程实例有没有正常结束未结束的实例历史表里可能只有部分数据。5. 避坑与排查部署和改造时最容易翻车的几处5.1 流程启动报找不到定义现象是提交表单后接口报process definition not found。原因是流程定义没有部署或者部署的 key 和代码里写的对不上。解决方法是进流程模型管理页看有没有已部署的定义没有就上传 BPMN 文件部署有的话核对 key 大小写。部署后引擎会往act_re_procdef表写记录直接查这张表最快。5.2 审批人收不到待办现象是流程启动了但指定的人登录后待办为空。原因通常是审批人变量传的是用户名而引擎里存的是用户 ID两边对不上。解决方法是统一用用户 ID 作为 assignee或者在查询待办时做一次转换。查act_ru_task表的assignee_字段看存进去的值和登录用户能不能匹配上。5.3 条件分支永远走同一条路现象是无论天数多少流程都走同一个分支。原因是条件表达式里的变量名和启动时传的 key 不一致或者变量类型不对导致比较失败。解决方法是启动流程后查act_ru_variable表看变量实际存进去的名字和值再和 BPMN 里的表达式逐字比对。数值比较时确认变量是 Number 类型而不是 String。5.4 中文乱码现象是审批意见或表单里的中文存进数据库变成问号。原因是数据库、连接串、表字段三处字符集不统一。解决方法是建库时用 utf8mb4连接串加characterEncodingutf8表字段确认是 utf8mb4。已经乱码的数据改不回来只能重新录入。5.5 前端菜单加载不出来现象是登录成功但侧边栏空白。原因是角色没有关联菜单或者菜单接口返回的数据结构前端没解析对。解决方法是查角色菜单关联表有没有数据再看接口返回的 JSON 层级和前端取值路径是否一致。开发时可以先在接口层打个日志确认数据出没出来。6. 二次开发把通用流程改成你自己的业务流拿到这套源码后最常改的三处是流程定义、表单字段和审批人规则。流程定义直接在 BPMN 文件里加节点、改条件表单字段在设计器里加同时在后端buildVars里补上变量映射审批人规则如果只是固定人改配置就行如果要按部门动态找人就在启动前查一次组织架构把结果塞进变量。我一般会先跑通一条最简单的单节点流程确认引擎、权限、表单三块都正常再往上加分支和会签。会签节点要设multiInstance属性指定集合变量和完成条件这块容易配错配完先用两个审批人测一遍。改造时别急着删原有流程新建一个 key 做测试跑通了再切换。验证改造是否成功看三个地方流程实例能不能正常结束、历史表里节点顺序对不对、待办和已办列表数据准不准。这三个都对了基本就没问题。从那以后我每次改流程定义都强制先跑一遍单节点冒烟测试再动复杂分支省得回头在历史表里捞数据对账。希望帮到你。本文还有配套的精品资源点击获取