OA审批系统源码实战:从启动到二次开发的完整指南
简介这是一套面向企业信息化建设者与Java开发者的OA办公自动化系统项目源码适合需要理解办公流程数字化、审批引擎与权限体系的中高级学习者参考。资源包共1212个文件约17.92MB以415个js前端脚本、186个gif界面素材、177个class与84个java后端源码为核心辅以72个xml配置、56个jar依赖、51个html与46个jsp页面、49个css样式及19个ftl模板完整覆盖从视图层到业务层的工程结构。内容围绕需求分析、功能模块设计、流程引擎、权限管理、系统集成、移动办公、报表分析、实施培训与后期维护等关键环节展开可帮助读者梳理公文管理、审批流转、会议与资产管理等模块的实现思路理解流程可配置化与分级权限控制的落地方式。目前已有385人学习下载适合作为课程设计、毕业设计或企业OA选型的技术参照。1. 从一堆散装审批到一套能跑的系统OA 项目到底在解决什么很多团队都经历过这种局面请假走群聊、报销靠邮件、采购审批用共享表格流程一多就乱谁批过、卡在谁那、历史记录在哪全靠人肉翻聊天记录。这套 OA 系统项目要解决的就是这件事——把审批流、表单、权限、通知这几块从散装状态收进一个能跑、能改、能扩展的后台系统里。它适合两类人一类是手上正好有这套源码、想先跑起来看效果的开发者另一类是想拿它当脚手架改出自己公司内部审批工具的熟手。整套项目围绕「流程可配置、表单可扩展、权限可控制」三个目标搭起来不是那种只能看不能改的演示壳子。2. 技术选型与目录结构先看清这套 OA 是怎么搭起来的2.1 后端技术栈与分层思路这套 OA 项目后端常见做法是 Spring Boot MyBatis-Plus 的组合权限层用 Spring Security 或 Sa-Token 兜底流程引擎部分如果项目里带了 Activiti 或 Flowable那审批流转就是引擎驱动如果没有多半是自研的状态机。数据库一般是 MySQL 8缓存用 Redis 存登录态和流程节点缓存。分层上基本是 controller / service / mapper / entity 四层外加一个 workflow 或 flow 包专门放流程相关逻辑。这样分的好处是审批逻辑不跟业务 CRUD 混在一起后面要加新流程类型时改的是 flow 包不动主业务。// 典型的 Controller 层入口接收前端提交的审批请求 RestController RequestMapping(/api/leave) public class LeaveController { Autowired private LeaveService leaveService; // 提交请假申请返回流程实例 ID PostMapping(/submit) public Result submit(RequestBody LeaveForm form) { // form 里包含申请人、天数、起止时间、审批人链 String processId leaveService.startProcess(form); return Result.ok(processId); } }这段代码里LeaveForm是前端传上来的表单对象startProcess内部会做两件事落库一条业务记录同时调流程引擎启动一个实例。参数processId是后续查审批进度、催办、撤回的唯一凭证。如果你拿到的项目里没有flow包那大概率流程状态是直接存在业务表的一个status字段里改起来更直接但扩展性差一些。2.2 前端结构与页面组织前端多数是 Vue 2 或 Vue 3 Element UI / Element Plus目录里会有views/oa/这样的文件夹下面按模块分leave、expense、purchase、notice。每个模块里通常是一个列表页 一个表单页 一个详情页。路由配置里会看到meta: { title: 请假申请, requiresAuth: true }这种写法requiresAuth控制是否需要登录有些项目还会加roles字段做按钮级权限。表单页一般用el-form配合rules做校验提交时调后端/submit接口。// 前端提交请假申请的核心逻辑 async submitLeave() { // 先做表单校验不通过直接返回 const valid await this.$refs.leaveForm.validate(); if (!valid) return; // 组装审批人链通常是上级 - 部门负责人 - HR const payload { ...this.form, approvers: this.buildApproverChain() }; const res await submitLeaveApi(payload); if (res.code 200) { this.$message.success(提交成功等待审批); this.$router.push(/oa/leave/list); } }buildApproverChain这个方法值得留意它决定了审批顺序。有些项目是写死的有些是从组织架构表里动态查的。如果你要改成「金额大于 5000 加一级审批」改的就是这个方法。2.3 目录结构速查目录作用src/main/java/.../controller接口入口参数校验src/main/java/.../service业务逻辑流程启动与回调src/main/java/.../flow流程定义、节点处理、审批人解析src/main/java/.../mapper数据库操作src/main/resources/processesBPMN 流程文件如果有引擎src/views/oa前端页面按模块分文件夹src/api/oa前端接口封装提示先看flow包和processes目录能快速判断这套 OA 是引擎驱动还是状态机驱动这决定了你后面改流程的难度。3. 跑起来从数据库到登录页的完整启动链路3.1 数据库初始化与配置修改拿到源码后第一件事不是急着mvn spring-boot:run而是先把数据库建好。项目里一般会带一个sql/目录里面有oa_schema.sql和oa_data.sql前者建表后者塞初始数据管理员账号、部门、角色。# 建库并导入 mysql -u root -p -e CREATE DATABASE oa_db DEFAULT CHARSET utf8mb4; mysql -u root -p oa_db sql/oa_schema.sql mysql -u root -p oa_db sql/oa_data.sql导入完检查两张表sys_user里有没有 admin 账号sys_role里有没有超级管理员角色。如果oa_data.sql里没塞登录会一直提示密码错误这是最常见的翻车点。然后改application.ymlspring: datasource: url: jdbc:mysql://localhost:3306/oa_db?useUnicodetruecharacterEncodingutf8 username: root password: 你的密码 redis: host: localhost port: 6379Redis 如果本地没装要么装一个要么把缓存相关配置注释掉但登录态可能依赖 Redis注释后要改成本地 Map 存储不推荐。3.2 后端启动与常见报错后端启动命令就是标准的 Maven 或 Gradle# Maven 项目 mvn clean package -DskipTests java -jar target/oa-system.jar # 或者直接跑 mvn spring-boot:run启动时如果报Table oa_db.act_ge_property doesnt exist说明项目用了 Flowable 或 Activiti但建表脚本没跑全。解决办法是找到引擎自带的建表 SQL或者把spring.flowable.database-schema-update设成true让引擎自动建表。另一个高频报错是端口占用OA 项目默认 8080如果被占改server.port就行。3.3 前端启动与接口代理前端一般是npm install npm run serve跑起来后如果接口 404检查vue.config.js里的proxy配置devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }changeOrigin: true必须加否则跨域请求会被浏览器拦。登录页默认账号通常是admin / 123456具体看oa_data.sql里的密码字段有些项目存的是 BCrypt 加密后的值不能直接改明文。注意如果登录后菜单是空的多半是角色和菜单的关联表没数据去sys_role_menu里补几条记录。4. 核心模块拆解审批流、表单、权限三块怎么联动4.1 审批流的状态流转与节点处理审批流的核心是一个状态机。以请假为例状态可能是草稿 - 待审批 - 审批中 - 通过 / 驳回 / 撤回。每次状态变更都要落一条审批记录记录操作人、时间、意见。// 审批节点处理的核心逻辑 public void approve(String taskId, String approver, String comment, boolean pass) { // 1. 查当前任务 Task task taskService.createTaskQuery().taskId(taskId).singleResult(); if (task null) throw new BizException(任务不存在或已处理); // 2. 记录审批意见 taskService.addComment(taskId, task.getProcessInstanceId(), comment); // 3. 根据通过与否决定流向 MapString, Object vars new HashMap(); vars.put(approved, pass); taskService.complete(taskId, vars); // 4. 更新业务表状态 leaveMapper.updateStatus(task.getProcessInstanceId(), pass ? APPROVED : REJECTED); }vars里的approved是流程分支的判断条件BPMN 文件里会用${approved}决定走通过线还是驳回线。如果你要加「会签」——多个人都通过才算过改的是 BPMN 里的multiInstance配置不是这段 Java 代码。4.2 表单动态渲染与字段扩展表单这块简单项目是每个模块写死一个 Vue 页面复杂一点的是后端返回表单配置 JSON前端动态渲染。后者扩展性好加字段不用改前端代码。// 动态表单渲染根据后端返回的 schema 生成表单项 renderForm(schema) { return schema.map(item { switch (item.type) { case input: return el-input v-model{this.formData[item.field]} /; case select: return el-select v-model{this.formData[item.field]} {item.options.map(opt el-option label{opt.label} value{opt.value} /)} /el-select; case date: return el-date-picker v-model{this.formData[item.field]} /; } }); }schema里每个对象包含field、type、label、options四个关键字段。要加一个「紧急程度」下拉框只需在数据库的表单配置表里加一条记录前端不用动。4.3 权限控制菜单、按钮、数据三层权限分三层菜单权限决定你能看到哪些页面按钮权限决定你能点哪些操作数据权限决定你能看谁的数据。菜单和按钮权限一般用角色关联登录时后端返回权限码列表前端用指令控制显隐// 自定义指令 v-permission控制按钮显隐 Vue.directive(permission, { inserted(el, binding) { const hasPerm store.getters.permissions.includes(binding.value); if (!hasPerm) el.parentNode.removeChild(el); } });数据权限复杂一些常见做法是在 SQL 里拼条件比如部门负责人只能看本部门数据。改的时候注意别把WHERE条件拼错否则要么看不到数据要么看到不该看的。提示权限码建议统一格式比如oa:leave:approve别用中文或随机字符串后面排查问题会省很多事。5. 避坑与排查跑这套 OA 时最容易卡住的几个地方5.1 登录成功但接口 401现象登录接口返回 token但后续请求全部 401。原因通常是前端没把 token 放进请求头或者后端拦截器配置的路径不对。解决检查axios拦截器里有没有config.headers.Authorization token以及后端WebSecurityConfig里放行的路径是否包含登录接口。5.2 流程启动后查不到待办现象提交申请成功但审批人登录后看不到待办任务。原因多半是审批人 ID 传错了或者流程定义里的候选人变量名和代码里不一致。解决去act_ru_task表里查ASSIGNEE_字段看是不是空或错值再对照 BPMN 文件里的assignee配置。5.3 前端打包后刷新 404现象npm run build后部署首页能打开刷新子页面就 404。原因是 history 路由模式需要服务端配置 fallback。解决Nginx 里加try_files $uri $uri/ /index.html;或者把路由模式改成 hash。5.4 数据库时间差 8 小时现象审批记录里的时间比实际时间少 8 小时。原因是 JDBC 连接没设时区。解决连接串加serverTimezoneAsia/Shanghai或者把 MySQL 全局时区设对。5.5 修改流程后旧实例报错现象改了 BPMN 文件重新部署之前跑了一半的流程实例报错。原因是新旧流程定义版本不兼容。解决改流程时尽量只加节点不删节点必须删的话先把旧实例跑完或手动终止。6. 二次开发把这套 OA 改成自己公司能用的样子拿到源码后最直接的改造点是审批人链。原项目多半是「上级 - 部门负责人 - HR」这种固定顺序但实际公司里可能是「直属上级 - 分管领导 - 财务」而且金额不同走的线也不同。改法是重写buildApproverChain方法从组织架构表里动态查而不是写死。// 改造后的审批人链根据金额和部门动态计算 public ListString buildApproverChain(LeaveForm form) { ListString chain new ArrayList(); // 第一级直属上级 chain.add(orgService.getDirectLeader(form.getUserId())); // 第二级金额大于 5000 加分管领导 if (form.getAmount() 5000) { chain.add(orgService.getDeptLeader(form.getDeptId())); } // 第三级HR 兜底 chain.add(orgService.getHrUserId()); return chain; }改完这个方法后验证方式是提交一笔金额 3000 和一笔 6000 的申请看审批链是否不同。如果相同检查orgService查出来的领导 ID 是不是空。第二个改造点是表单字段。原项目的请假表单可能只有「天数」和「事由」你要加「请假类型」和「附件」。改法是先在数据库表单配置表里加两条记录然后在前端renderForm的switch里加upload类型分支。第三个改造点是通知。原项目可能只有站内信你要加邮件或企业微信通知。做法是在流程状态变更后发一个事件监听器里调通知服务。注意别把通知逻辑写在approve方法里否则流程一慢通知就堵。改造点改动位置验证方式审批人链flow包下的buildApproverChain提交不同金额申请看链路表单字段表单配置表 前端renderForm新增字段能否渲染和提交通知方式事件监听器 通知服务审批后能否收到邮件权限粒度sys_role_menu 前端指令不同角色登录看按钮显隐我自己的习惯是每次改完流程相关代码先跑一遍「提交 - 审批 - 驳回 - 重新提交」的完整链路再去看数据库里act_ru_task和业务表的状态是否一致。这个习惯帮我挡掉过好几次「流程卡死但页面不报错」的玄学问题。从那以后我每次动流程配置都强制走一遍全链路希望帮到你。本文还有配套的精品资源点击获取

相关新闻

纯JSP+Servlet人事系统:员工异动审批与PDF生成实战

纯JSP+Servlet人事系统:员工异动审批与PDF生成实战

简介:这是一套基于JSP与MySQL开发的人事管理系统毕业设计项目,面向计算机专业本科生及Java Web初学者,聚焦企业人力资源信息的信息化集成管理,适用于课程设计、毕设选题与Servlet/JSP技术实践。资源包共108个文件,包含…

2026/10/18 12:52:39 阅读更多 →
Web前端摄像头调用安全实战:权限模型、攻击场景与防护清单

Web前端摄像头调用安全实战:权限模型、攻击场景与防护清单

1. 摄像头权限:看似简单的水龙头,却是整个安全体系的关键阀门这几年做Web前端,经常遇到产品经理拿着一个“调用摄像头”的需求就过来了:人脸识别登录、扫码、拍照上传、视频客服、AR试妆,看起来都是几行 getUserMedia …

2026/10/18 12:52:39 阅读更多 →
JSP+Servlet+MySQL人事管理系统毕设实战指南

JSP+Servlet+MySQL人事管理系统毕设实战指南

简介:这是一套基于JSP与MySQL开发的人事管理系统毕业设计项目,面向计算机专业本科生及Java Web初学者,聚焦企业人力资源信息的信息化集成管理,覆盖员工信息维护、管理员登录注册、日志校验等核心功能模块,可作为课程设…

2026/10/18 12:52:39 阅读更多 →

最新新闻

降AI万能公式是伪命题?从AI检测原理到可复用改写框架的完整指南

降AI万能公式是伪命题?从AI检测原理到可复用改写框架的完整指南

“降AI万能公式”最近在内容创作圈子里热度很高,很多朋友私信问我:网上流传的那些“降AI提示词”“一键去AI味模板”到底有没有用?是不是真有那么一套万能公式,套进去就能让AI写的字变成“人写的”?我认真拆解过这些方…

2026/10/18 17:44:45 阅读更多 →
LangGraph实战:构建有状态的AI Agent工作流

LangGraph实战:构建有状态的AI Agent工作流

LangGraph 是近两年 LLM 应用开发里绕不开的一个名字。我最初是被它的“有状态”这三个字吸引过去的,因为之前用常见的 Agent 框架做多步骤任务时,最头疼的就是状态管理——每个节点各自为政,对话历史要手动拼接,分支逻辑要写在业…

2026/10/18 17:44:45 阅读更多 →
openLava 4.0集群调度器实战指南:安装配置、作业提交与故障排查

openLava 4.0集群调度器实战指南:安装配置、作业提交与故障排查

简介:openlava 4.0 是经典的开源集群调度管理工具,这份源码安装包面向集群运维人员、HPC学习者和希望理解作业调度机制的技术人员。尽管官方已停止维护,但其核心设计与命令体系深刻影响了IBM LSF,至今仍有借鉴价值。压缩包内含501…

2026/10/18 17:44:45 阅读更多 →
终端跑酷游戏moon-buggy在KeyarchOS上的安装与玩法实战

终端跑酷游戏moon-buggy在KeyarchOS上的安装与玩法实战

之前在终端里跑htop、vim、tmux大家都见多了,但你见过在终端里玩跑酷吗?moon-buggy就是这样一款能在纯文本终端里运行的经典跑酷游戏——你驾驶一台月球车,在布满陨石坑的月面上一路狂奔,空格键跳跃躲坑,跑得越远分数越…

2026/10/18 17:44:45 阅读更多 →
随机森林预测电池RUL:不依赖物理模型的工业级鲁棒方案

随机森林预测电池RUL:不依赖物理模型的工业级鲁棒方案

简介:本资源是一套基于Python随机森林算法的锂离子电池剩余寿命(RUL)预测完整实践方案,面向机器学习入门者与电池健康状态研究初学者,适用于课程设计、毕设项目及工程实训场景。资源包共117个文件,含106个原…

2026/10/18 17:44:45 阅读更多 →
TensorFlow Lite端侧推理集成指南:模型转换、性能优化与避坑实践

TensorFlow Lite端侧推理集成指南:模型转换、性能优化与避坑实践

做端侧AI这么久,TensorFlow Lite集成这个坑,我前后踩了大半年才彻底理顺。去年接手一个离线质检项目,现场环境没有稳定网络,只能在某个嵌入式设备上跑一个图像分类模型。模型在训练环境里精度很正常,一到端侧不是转不动…

2026/10/18 17:43:44 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →