从接到需求到把系统跑起来,中间隔着的往往不是代码,而是一堆文档没写清楚的环境问题、版本兼容问题和逻辑理解问题。最近帮某家公司的行政部搭建内部管理系统,他们在用Excel表格和微信群里转来转去的审批消息管考勤、管请假、管报销,混乱程度堪称灾难。于是我基于一套SpringBoot后端+Vue前端+MySQL的源码,快速部署了一套企业OA管理系统,实际跑下来,这套系统的完整度确实对得起"可直接运行"这四个字。
这篇就把我从拿到源码、配置环境、启动前后端、理解核心设计,到最终二次改造落地的完整过程写下来。内容包括这套系统到底能做什么、功能边界在哪、技术选型为什么是这套组合、源码结构怎么读懂、快速启动的每一步操作、核心功能(登录鉴权、权限控制、审批流)的实现思路,以及我在实操中踩过的真实坑和排查链路的记录。无论你是准备拿它做毕设的学生,还是想给公司快速搭一套内部工具的技术负责人,这篇文章都可以作为一份详细的参考。
1. 这套OA系统解决什么问题:功能边界与应用场景
先说结论:这不是一套只停留在Demo层面的教学代码,而是一套覆盖企业日常办公高频场景的信息管理系统。我拿到的版本里,功能模块比较完整,按企业实际使用频率来排,大概可以分成这么几个层级。
1.1 核心功能模块拆解
基础的用户管理模块是绕不开的第一层。系统里有用户账号、部门、角色这三个基础实体,管理员可以在后台维护组织架构。企业内部管理系统的第一要务就是"谁拥有什么权限、能看到什么数据",这部分做不好,后面所有模块都会失控。这套系统在用户模块做了很清晰的设计:用户归属于部门,角色可以绑定多个用户,权限通过角色间接分配给用户,也就是经典的RBAC模型(基于角色的访问控制)。
第二层是审批流模块。包括请假申请、报销申请、用章申请、一般事项审批等几种常见单据类型。申请人发起流程,系统根据预设的审批规则(比如部门主管审批、再到分管领导、再到行政备案)逐级流转,每个节点有审批人、审批意见、审批时间记录。这一层是OA系统区别于普通信息管理系统最核心的地方。
第三层是信息发布与内部协作模块。包括公告通知、内部新闻、任务分派与进度反馈。这套系统里的公告模块支持富文本编辑,发布后可以在首页工作台直接推送,对行政人事部门做制度宣贯非常实用。
1.2 系统边界:它能做什么,不能做什么
需要说明的是,这套系统不是万能的。它的定位是"企业内部办公与信息流转",不是ERP(企业资源计划系统),也没有财务管理、进销存、客户管理等业务系统的能力。如果你需要的是销售订单跟踪、库存盘点,那应该找专门的业务系统来做对接。另外,审批流属于轻量级工作流,通常支持固定路径的逐级审批,但不适合非常复杂的条件分支流程——那种需要引入独立的流程引擎(例如Activiti或Flowable)来做。
1.3 这套系统适合谁来用
我梳理了一下,这套源码适合三类人。
第一类是毕业生或转行做开发的初学者,把它作为完整的项目实战参考资料非常合适。因为它前后端分离、结构清晰、注释比较完整,麻雀虽小五脏俱全,从表设计到接口定义都有完整链路,比网上东拼西凑的教程强太多。
第二类是企业内部的技术人员,比如公司里就一个人管IT,需要快速上一套内部办公系统,不想从零开发,也不想买年费极高的商业OA,那么用这套源码改造部署是性价比极高的方案。
第三类是接私活的技术人。企业OA是外包领域的常青需求,拿一套基础功能完备的系统的源码做底子,按客户需求定制开发,比每次从空项目开始搭省太多时间。
2. 技术栈为什么是SpringBoot+Vue+MySQL:选型逻辑与合理设计
很多刚接触这套系统的读者会想当然认为技术栈就是"随便选的",其实不是。这套组合是当前中小型管理系统开发里最主流的搭配,几乎可以称得上"黄金三角",每个环节都有明确理由。
2.1 后端用SpringBoot的理由
SpringBoot在Java后端领域的地位不需要多说。它解决了Spring时代大量XML配置带来的痛苦,通过自动化配置把项目初始化成本压得非常低。对于OA这种以CRUD(增删改查)为核心的业务系统,SpringBoot提供的Spring Data JPA或MyBatis集成、Spring Security权限框架、全局异常处理机制,几乎覆盖了开发过程中的所有基础需求。
我特别在意的一点是SpringBoot的生态成熟度。做OA系统必然要处理登录鉴权、权限校验、文件上传、定时任务(比如考勤统计月末自动生成报表)这些通用需求,这些在SpringBoot里都有非常成熟的集成方案。遇到问题搜索一下,结果比用冷门框架多一到两个数量级,这个优势在排错时尤其值钱。
2.2 前端用Vue的理由
Vue是国内使用率极高的前端框架,上手平滑,从原生JS转到Vue基本没有太大心理负担。这套系统用Vue做单页应用,配合Element UI组件库,表格、表单、弹窗、分页这些管理后台的高频组件都是现成的,几天时间就能搭出像样的界面。
需要注意这里用的是Vue 2还是Vue 3,不同版本对应不同的工程化方式。从我拿到的源码来看是Vue 2 + Element UI的经典组合,虽然Vue 3 + Element Plus已经逐渐普及,但Vue 2这套组合在存量企业项目里仍大量存在,它最大的好处就是生态非常稳定,坑基本都被人踩完了。对于部署优先、稳定优先的OA场景,这不是落后,而是成熟。
2.3 数据库选MySQL的原因
MySQL和SpringBoot、Vue一样,属于管理系统的"默认选项"。开源免费、性能足够、运维资料多,很多生产环境(比如中小型公司的核心系统)都在用MySQL。OA系统本身需要的数据库能力并不复杂——事务、普通索引、备份恢复,MySQL全部能轻松胜任。而且源码里自带的SQL脚本往往直接兼容MySQL的语法格式,导入就能用,不需要做方言转换。
2.4 这套组合的真实性价比
从成本角度来看,SpringBoot、Vue、MySQL三条技术栈全部免费开源,没有授权费的概念,这对预算敏感的企业非常有吸引力。从人员角度来看,这三样的开发者数量在国内是最多的,招人容易、外包容易、后续维护也容易,不用担心人走了系统就没人碰得动。从开发效率来看,SpringBoot的Starter机制、Vue的组件化、MySQL的简单易用,三者叠加可以快速完成迭代。所以我一直认为,如果不是有特殊的性能或技术约束,中小型管理系统用这套组合是最稳妥的选择。
3. 读懂源码结构是改造的前提:前后端目录设计拆解
拿到一套源码先不要急着启动。花半小时把目录结构过一遍,跑通之后改动代码时才不会迷路。这一步我每次接新项目都会做,收益非常大。
3.1 后端目录结构与分层逻辑
SpringBoot后端的代码结构基本遵循经典的分层架构。package的组织逻辑一般是这样的:
controller:对外暴露RESTful接口,只负责接收参数和返回结果,不在这一层写业务逻辑service:核心业务逻辑层,事务管理、流程控制、业务校验都在这层完成mapper(或dao):数据访问层,封装对数据库的增删改查操作entity(或domain):数据库表映射的实体类config:配置类,包含跨域配置、拦截器配置、Swagger配置等common(或util):公共工具类、统一返回结果封装类、全局异常处理
我特意强调一下统一返回结果封装类。这套系统里所有接口返回的格式基本都是{ code: 200, msg: "操作成功", data: ... }这种结构。这个设计看着简单,实际非常重要:前端可以通过code值统一判断请求是否成功,统一弹出错误提示,而不需要每个接口单独处理异常状态。这也是前后端分离项目里约定接口规范的关键环节。
3.2 前端目录结构与工程化
Vue前端的目录结构是标准的前端工程化布局:
src/api:接口请求定义,每个模块一个文件,比如user.js放用户相关接口,approval.js放审批相关接口src/router:路由定义,每页一个路径,配置了全局前置守卫src/store:状态管理(Vuex或Pinia),主要存用户信息、登录令牌、菜单权限src/views:页面组件,按业务模块划分目录src/components:公共组件,比如上传组件、富文本编辑器、分页组件src/utils:工具函数,比如request.js里封装axios实例、请求拦截器、响应拦截器
这里有个值得重点看的设计:路由和菜单权限是怎么关联的。很多初学者做管理系统会把菜单写死在前端,但工程上正确的做法是动态路由——用户登录后,后端根据角色返回可访问的菜单和数据权限,前端把菜单与路由做映射关系,渲染出属于该用户的工作台。这套源码就实现了这个逻辑,拿到手后可以仔细看看。
3.3 配置文件里的关键信息
后端的application.yml(或application.properties)是启动的关键。需要重点关注以下几项配置:
- 数据源配置:数据库地址、端口、库名、用户名、密码
- JPA或MyBatis配置:是否自动建表(
ddl-auto)、SQL日志是否打印 - 文件上传路径配置:本地存储目录在哪个位置
- 服务端口配置:默认一般是8080
前端的vue.config.js里有开发环境的代理配置,把/api开头的前端请求转发到后端服务地址,这是解决开发环境跨域问题的标准做法。如果启动后发现登录请求报错,先看这里的代理地址是否正确。
4. 从环境准备到页面出现:快速启动的完整操作记录
"可直接运行"这个描述不是虚的,但有一个前提——你得先把环境准备好。这一节把我实际的启动过程完整记录下来,包括每个步骤、每个命令和每个注意点。
4.1 环境清单
开始之前先确认本机安装了这些东西:
| 软件 | 版本要求 | 说明 |
|---|---|---|
| JDK | 1.8或以上 | 推荐1.8,稳定且兼容性最好 |
| Maven | 3.6+ | 包管理工具,负责依赖下载 |
| MySQL | 5.7或8.0 | 建议5.7,兼容性更广 |
| Node.js | 12及以上 | 前端构建工具链所需,建议14以上 |
| npm/yarn | 任意新版 | 安装前端依赖 |
| IDEA/VSCode | 任意 | 开发工具,IDEA对Java更友好 |
前端工程本身使用npm管理依赖。npm在国内环境下经常下载速度慢,建议先设置镜像源:npm config set registry https://registry.npmmirror.com,否则安装依赖那一步可能要等很久。
4.2 数据库准备:导入SQL脚本
源码目录下一般会有一个sql文件夹,里面是数据库初始化脚本。在MySQL中执行以下步骤:
# 登录MySQL mysql -u root -p # 创建数据库 CREATE DATABASE IF NOT EXISTS oa_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 选择数据库 USE oa_system; # 导入数据 SOURCE /path/to/sql/oa_system.sql; # 退出 exit;字符集特意选择utf8mb4,这是支持四字节emoji字符的字符集,避免后期短信通知内容或审批意见里包含特殊字符时出现乱码。数据脚本导入成功后,重点看一下sys_user表,管理员账号通常在这里,初始密码如果是明文存在库里,说明源码默认没有对密码加密,后续正式使用前需要改为BCrypt等摘要算法加密存储。
4.3 后端启动:修配置,跑起来
导入SQL后,用IDEA打开后端工程,等待Maven把依赖下载完成。这个等待过程取决于网络环境,第一遍可能要几分钟,这不是卡住了,耐心等就好。
接下来修改配置文件application.yml里的数据库连接信息:
spring: datasource: url: jdbc:mysql://localhost:3306/oa_system?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password_here driver-class-name: com.mysql.cj.jdbc.Driver需要注意serverTimezone参数,如果MySQL设置的是默认时区,连接时没有这个参数可能会报时区错误。修改完成后,找到启动类(通常叫OaApplication或类似名字),右键运行。看到日志输出Started OaApplication in xx seconds或者Tomcat started on port(s) 8080,说明后端已经启动成功。
4.4 前端启动:装依赖,跑起来
解压前端工程,在项目根目录打开终端:
# 安装依赖 npm install # 启动开发服务器 npm run serve开发服务器默认跑在8080端口,如果和后端端口冲突,可以在vue.config.js里修改devServer的端口。启动成功后终端会显示访问地址,通常是http://localhost:8080。如果用Vue CLI创建的项目且后端启动正常,前端启动后会通过代理把请求转发到http://localhost:8081(后端实际端口),这样就不会发生端口冲突。
打开浏览器访问前端地址,看到登录页面后,输入管理员账号密码。如果系统正常跳转到工作台,展示出菜单、待办事项、公告列表,说明整套系统已经成功串成一条链路了。
4.5 第一次登录后必做的三件事
系统能登录只是开始。我建议第一次登录后用管理员身份做三件事:
第一,检查系统初始化的菜单数据是否完整。如果某些业务模块入口缺失,多半是数据库脚本里的菜单表数据没插全,需要对比SQL脚本是否有完整的INSERT语句。
第二,创建几个不同角色的测试账号(部门主管、普通员工、人事管理员),用这些账号分别登录,验证权限控制是否生效。这一步非常关键,很多改过代码的系统会在没有权限控制的情况下让所有用户看到全部菜单——这不是开发模式应当出现的状态。
第三,测试一个完整的请假审批流程。A发起申请,B审批通过,C审批拒绝,验证状态流转是否正常,审批记录是否留痕。流程如果跑通了,这套系统基本就可以放心投入使用。
5. 核心功能背后的实现思路:登录鉴权、权限模型与审批流
启动成功只是第一步,要真正改造和用好这套系统,需要理解它内部几个核心机制的设计思路。我挑了三个最重要的点来讲,这几个点也是面试、答辩、二次开发时最常被问到的。
5.1 登录鉴权:从Session到JWT
传统单体应用常用Session方式维持登录态,前端存Cookie,后端存Session。但前后端分离的项目里,更普遍的做法是使用JWT(JSON Web Token)。这套系统采用的就是JWT方案。
用户输入账号密码后,后端验证通过会生成一个包含用户ID、用户名、角色标识等信息的令牌(Token),返回给前端。前端把Token存在本地存储中,之后每次请求都在HTTP头部的Authorization字段带上这个Token(通常格式是Bearer <token>)。
后端使用拦截器或过滤器统一校验请求头,Token有效则放行,无效或过期则返回401状态码。这样做的好处是后端是无状态的——不存储会话信息,便于将来水平扩展多实例部署,也因为前端把身份标识放在请求里,天然适合移动端和PC端共用同一套API。
这套系统的拦截器配置在config包下的WebMvcConfigurer实现类里,可以在那里配置哪些路径需要鉴权、哪些路径对外开放(比如登录接口往往是放行的,静态资源也是放行的)。
5.2 RBAC权限模型:用户、角色、权限的三层映射
权限控制是这个系统的核心能力之一。权限模型沿用经典的RBAC设计,具体落地为四张核心表:
sys_user:用户表,记录账号、密码、姓名、所属部门sys_role:角色表,定义超级管理员、部门主管、普通员工等角色sys_user_role:用户-角色关联表,记录某个用户拥有哪些角色sys_role_menu:角色-菜单/权限关联表,记录某个角色可以访问哪些菜单和操作按钮
通过这种多对多映射,管理员只需调整角色和菜单的关联关系,就能控制一批用户的访问范围,而不需要逐个用户配置权限。这也是权限控制的常规操作。
前端的对应实现是:登录成功后请求"获取当前用户信息"接口,后端返回该用户可访问的菜单列表(树形结构)和按钮权限标识;前端用Vue Router的addRoutes方法动态添加路由,用自定义指令或v-if控制按钮级权限的显示。这套联动逻辑在整个源码里是精华部分,值得认真读通。
这里有个细节要补充:菜单权限和接口权限是两个层面。前端隐藏菜单只是不让用户"看到"入口,但用户如果懂技术,手动调用接口,后端必须也校验接口权限,否则就会越权。所以这套系统的后端接口同样根据登录用户身份做了操作级校验,而不是仅仅依赖前端隐藏。这个"前后端双重校验"的设计理念,是权限系统安全性的关键。
5.3 审批流设计:状态机思维与操作留痕
审批流是OA系统的灵魂。虽然它没有引入流程引擎,但用数据库字段+状态流转实现了一套可用的轻量级审批流程。
核心是审批单主表(例如approval_form)和审批记录表(例如approval_record)。主表记录单据类型、申请人、当前状态、表单内容;记录表记录每一步的操作人、操作结果(同意/驳回)、操作意见、操作时间。
状态流转用一个整数字段表示,比如:
| 状态值 | 含义 |
|---|---|
| 0 | 草稿(已保存未提交) |
| 1 | 审批中(已提交,等待当前审批人处理) |
| 2 | 已通过(所有审批节点均同意) |
| 3 | 已驳回(任意审批节点驳回) |
| 4 | 已撤回(申请人在审批中撤回) |
每次操作不仅更新主表状态,还在记录表中追加一条记录。这样设计保证了两点:第一,审批过程可以完整追溯,每一步谁做了什么操作都有案可查;第二,系统可以随时知道当前单据状态,方便做待办提醒和列表筛选。
需要提一下的是,这套系统里的审批路径一般是预先定义好的固定链路(比如部门主管→分管领导→人事备案),不是完全自由配置的流程编排。对于大部分企业日常场景,这种固定链路已经足够用了。如果需要支持不同金额范围走不同审批层级这种条件分支,需要在现有表结构上扩展配置表,或者引入真正的流程引擎,这是一条清晰的演进路线。
5.4 前端接口调用:axios封装与拦截器
前端所有接口的调用都不是直接裸用axios,而是统一封装在了utils/request.js模块里。这个文件里主要做了三件事:
- 创建axios实例,设置基础URL(
baseURL)为/api - 请求拦截器:每次请求前从本地存储获取Token,注入请求头的Authorization字段
- 响应拦截器:统一处理HTTP响应,当code为200时返回data给页面;当code为401时跳转登录页;当code为500时弹出错误提示
这样做的好处是页面里只需要专注处理业务数据,不用重复写错误处理逻辑。我在改这套代码的时候给响应拦截器加了一个功能:当Token即将过期时自动刷新Token并重放请求,避免用户操作到一半突然被踢出登录态。当然,这一步需要后端配套一个Token刷新接口,实现起来也比较直观。
6. 实操踩坑清单:我跑这套系统时遇到过的真实问题
这部分是我觉得最有价值的内容。我把实际跑这套系统以及给公司部署过程中遇到的典型问题整理成了清单,每个问题都附上了排查思路和最终解决方法,以后遇到类似问题可以少走弯路。
6.1 数据库连接失败排查
第一次启动后端,看到日志里报了数据库连接异常。排查链路是这样的:
先确认MySQL服务是否已经启动,命令行里执行mysql -u root -p能登录就说明服务正常。接着检查连接地址和密码是否正确,尤其注意密码里是否包含特殊字符(比如@、#),如果包含,在yml文件里要用字符串引号包起来。然后发现改为utf8mb4并指定serverTimezone后,连接正常了。所以遇到数据库连接问题,遵循的排查顺序应该是:服务是否启动 → 连接地址是否正确 → 账号密码是否正确 → 驱动是否匹配 → 时区参数是否缺失。
6.2 前后端联调时请求404
后端启动成功,前端也启动成功,但每次点击登录都提示接口不存在。排查发现是整个代理没有生效——前端请求指向了http://localhost:8080/api/login,而后端服务跑在8081端口。
这种情况导致404的原因很典型。解决方式是检查vue.config.js的devServer代理配置,确保:
devServer: { proxy: { '/api': { target: 'http://localhost:8081', // 后端实际地址 changeOrigin: true } } }修改完成后重启前端开发服务器,问题即消失。这里也提醒大家注意,修改vue.config.js、环境变量这类配置文件后,通常都需要重启开发服务器才能生效,而不是保存就自动生效。
6.3 前端路由刷新后404
这是部署到Nginx后经典的问题,需要特别重视。Vue是单页应用,所有页面都在一个index.html里,由前端路由控制切换。如果刷新一个深层路由的URL(比如/system/user),Nginx会去服务器找这个路径的物理文件,找不到就返回404。
解决方法是让Nginx在找不到对应文件时回退(fallback)到index.html:
location / { try_files $uri $uri/ /index.html; }如果是开发模式下刷新404,通常需要检查使用的是history模式还是hash模式。改用hash模式(URL带#符号)可以减少这个问题的出现,但history模式更美观,配合Nginx配置完全可用。生产部署时我建议保留history模式,只需要正确配置Nginx回退。
6.4 Token过期后的"幽灵操作"
系统运行一段时间后,有人反馈"明明一直在用,过一段时间点击提交还是跳登录页"。排查后发现是Token有效时长的配置太短,且设置的是绝对过期时间,不管这段时间内用户是否有操作,到期一律失效。
解决方案分两步:
- 调整Token有效期配置(比如从30分钟调整到2小时)
- 在JWT过期拦截时实现"刷新Token"接口:如果访问令牌过期但刷新令牌有效,自动生成新的访问令牌返回给前端,前端透明地重新发送原始请求
这样用户的操作不会中断,体验和安全性都能兼顾。需要注意刷新令牌本身也有有效期,且要服务端记录刷新令牌的状态,方便泄露时强制失效。
6.5 大量用户同时在线时数据库连接数被打满
系统上线后第一次全员使用,大约一百多人同时在线操作,后台报错连接池不够了。分析原因是默认的连接池配置太小,通常几百人并发访问管理后台时,默认配置不足以支撑。
解决办法是调整HikariCP连接池参数:
spring: datasource: hikari: maximum-pool-size: 50 minimum-idle: 10 connection-timeout: 30000同时检查MySQL自身的最大连接数配置,确保两者适配。这里要提醒的是连接池不是越大越好,每一条连接都占内存和数据库资源,太大反而会拖垮数据库。对于中小型企业内部系统,50到100并发连接已经非常宽裕。
7. 从开发环境到生产部署:真正落地的关键步骤
开发环境跑通只是完成了第一步。把系统真正"交付"给业务部门使用,还需要完成下面的工作。
7.1 前端打包与Nginx部署
前端部署时执行构建命令:
npm run build构建完成后,项目根目录的dist目录就是所有静态文件。把它们上传到服务器的任意目录,比如/opt/oa-frontend/,然后配置Nginx作为静态文件服务器并做反向代理。
推荐的Nginx配置如下:
server { listen 80; server_name your_domain_or_ip; # 前端静态资源 root /opt/oa-frontend/dist; index index.html; # 解决history模式路由刷新404 location / { try_files $uri $uri/ /index.html; } # 后端API反向代理 location /api/ { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }有一个细节需要特别注意:代理到后端时,proxy_pass后面的地址是否带/api/路径,直接决定接口路径是否会被拼接替换。如果后端接口本身包含/api前缀,则proxy_pass http://127.0.0.1:8081;可以保持原路径转发;如果不带,需要在Nginx层做路径改写。这个细节在生产环境排查404和500类问题时非常关键。
7.2 后端生产环境部署
后端在IDEA里可以直接打包成可执行jar文件:
mvn clean package -DskipTests打包完成后,在target目录下得到.jar文件。使用Systemd或其他进程管理工具守护Java进程:
nohup java -jar oa-system.jar --spring.profiles.active=prod > logs/oa.log 2>&1 &注意使用--spring.profiles.active=prod指定生产环境配置。生产环境与开发环境的核心差异包括:
- 数据库连接信息、账号密码是独立的
- 文件上传路径要放到有充足磁盘空间的目录,最好单独挂载数据盘持久化
- 开启安全相关的配置:Token加密密钥改为强随机值、开启请求日志(但不打印敏感字段)、配置HTTPS证书
- MySQL的
ddl-auto要改为none或validate,严禁生产环境使用update自动改表结构,这点务必警惕
7.3 数据安全与备份策略
OA系统运行一段时间后,企业的重要业务流程数据都沉淀在里面了,数据备份就不是可选项而是必需品。MySQL的常规备份脚本或工具定时导出(例如每天凌晨mysqldump),保留最近30天的备份文件,同时兼顾异地备份。
我还想强调一点:生产环境的配置文件不要硬编码数据库密码,建议用环境变量注入,可以在部署时通过Systemd的Environment字段或环境管理文件替换。密码定期更换,数据库账号按需分配最小权限,避免全部应用共用一个root账号,这些基础的安全操作在部署时要养成习惯。
7.4 二次开发的可行扩展方向
系统跑稳了之后,可以根据实际业务继续扩展。几个投入产出比比较高的方向供参考:
- 接入企业微信/钉钉,实现审批消息推送到手机端,员工在手机上收到待办提醒,点击跳转到系统的H5页面
- 增加Excel导出功能:各部门考勤统计、报销汇总等常用报表,让管理者直接导出数据,不用在系统里手工整理
- 引入定时任务:每天定时统计考勤异常、超时未审批单据,自动发送提醒邮件或通知
- 文件管理模块接入对象存储:把附件、合同扫描件放到高可用的存储服务上,而不是存在本地磁盘,兼顾可靠性和扩容能力
实际做下来,这套SpringBoot+Vue+MySQL的企业OA管理系统,无论作为学习参考还是真实业务落地,都是一套相当扎实的底子。我从拿到源码到内部测试、部署上线的过程中,对它最大的感受是"该有的都有,改起来不费劲"——这句话在开源项目里其实是相当高的评价。希望这篇能帮你把它顺利跑起来,少踩几个我当初踩过的坑。