ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SpringBoot+Vue人事管理系统源码解析:从架构到权限设计

SpringBoot+Vue人事管理系统源码解析:从架构到权限设计 简介这是一套面向Java与前端初学者、全栈开发入门者的人事管理系统实战源码基于SpringBootVue实现前后端分离架构覆盖员工信息管理、部门维护、岗位配置、考勤统计等核心HR业务场景助力开发者快速掌握企业级应用的工程搭建、接口联调与权限控制实践。压缩包共189个文件含60个Java后端业务与控制器类、23个Vue组件及23个JS逻辑脚本、44个PNG图标资源、9个MyBatis XML映射文件以及yml配置、SQL初始化脚本、字体文件和静态资源整体体积6.98MB结构清晰、模块职责分明。目前已有546人学习下载源码已通过基础功能验证附带完整目录结构与标准化配置如.editorconfig、.gitignore、babelrc可直接导入IDE运行适合用于课程设计、毕业项目或技术栈整合练习。 前后端分离的人事管理系统这类项目在简历上出现的频率快赶上“学生管理系统”了但说句公道话能把它做得干净、规范、可以直接拿去二次开发的源码确实不多。很多朋友拿到手的所谓“源码”要么是培训机构几千块钱的培训项目代码里塞满了注释和教学模块要么是好几年前的老古董SpringBoot还在用1.x前端还是jQuery时代。今天要拆解的这份基于SpringBootVue的源码属于比较标准的企业级开发范本技术栈主流、权限模型完整、业务覆盖了人事管理的核心场景很适合用来做毕业设计、面试项目、或者作为自己公司内部系统的开发起点。这篇内容我会从整体设计思路、数据库建模、后端核心实现、前端页面落地、部署上线到常见坑位排查一步步拆开来讲。不管你是刚学完Java基础想找项目练手的新手还是已经在工作中需要搭建内部系统的开发者这套源码的很多设计思路和踩坑经验都能直接拿来用。1. 项目整体设计与技术选型1.1 为什么选择SpringBootVue这套组合先说个现实问题很多人在选技术栈的时候习惯性追求“新”SpringBoot 3.x出来了就一定要用最新的前端非要上Vue3TypeScript。但对于人事管理系统这类典型的业务系统稳定、生态成熟、招人容易才是真正的刚需。SpringBoot 2.x Vue 2 Element UI这套组合在这个领域几乎是“不败之地”。SpringBoot自带自动配置和starter机制把以前SSH时代各种繁琐的XML配置全部干掉开发效率提升非常明显。Vue 2配合Element UI组件库做后台管理界面简直就是流水线作业表格、表单、弹窗、分页这些组件拖过来就能用。这套源码选这个组合最大的好处就是学习曲线平缓、参考资料极多、遇到问题搜索一下基本都能找到答案。1.2 项目架构与目录规划展开源码之前先看整体的目录结构规划。这份源码采用的是标准的前后端完全分离架构前端和后端是两个独立的工程目录部署时也完全解耦。hrms-server/ # 后端工程SpringBoot ├── src/main/java │ └── com/hrms │ ├── controller/ # 控制层接收前端请求 │ ├── service/ # 业务逻辑层 │ ├── mapper/ # MyBatis数据访问层 │ ├── entity/ # 实体类对应数据库表 │ ├── dto/ # 数据传输对象承载接口入参出参 │ ├── config/ # 全局配置安全、跨域、拦截器 │ ├── common/ # 公共类统一返回、异常处理 │ └── utils/ # 工具类JWT、日期处理 └── src/main/resources ├── mapper/ # MyBatis XML文件 └── application.yml # 核心配置文件 hrms-web/ # 前端工程Vue ├── src/ │ ├── api/ # 接口请求层按模块拆分为独立JS文件 │ ├── assets/ # 静态资源 │ ├── components/ # 通用组件 │ ├── router/ # 前端路由配置 │ ├── store/ # Vuex状态管理 │ ├── utils/ # axios封装、权限校验工具 │ ├── views/ # 页面组件 │ └── App.vue # 根组件 └── package.json这个目录结构几乎是国内所有中后台项目的“标准答案”不管以后你拿到若依框架、芋道源码还是公司内部沉淀的项目目录风格基本八九不离十。后端按controller-service-mapper-entity分层职责边界清晰前端按api-views-store拆分方便多人协作时减少代码冲突。1.3 源码的核心价值在哪里说句实在话人事管理系统的CRUD本身并不难随便一个培训生都能写出来。这套源码真正的价值也最值得大家去读的地方在于三点。第一是权限管理的落地方式。人事系统里不同角色能看到的数据完全不同——普通员工只能看自己的考勤和薪资条HR专员能管理员工档案部门经理能看自己部门的报表超级管理员才能动系统配置。这种多级权限的控制不是简单地在接口上做判断而是从数据库表设计、后端拦截器、前端路由三个层面同时控制整套体系非常完整。第二是通用组件和工具类的封装。比如分页查询的通用封装、excel导入导出的工具类、统一异常处理机制这些都是实际企业项目里真正会用到的高频功能比单纯的CRUD有价值得多。第三是可二次开发的扩展性。这份源码的业务模块和基础框架耦合度控制得不错把员工管理、考勤、薪资这些核心业务模块单独拎出来看代码之间没有那种“牵一发动全身”的窘境。2. 数据库设计与权限模型2.1 人事系统核心表结构梳理打开源码配套的SQL脚本核心数据库表大概有十一张。我用一个表格把最核心的几张表列出来大家先对整体有个概念。表名业务含义核心字段备注sys_user系统用户表id, username, password, nickname, status和员工表分离用户可绑定员工sys_role角色表id, role_name, role_code, remark超级管理员、HR、部门经理、普通员工sys_menu菜单权限表id, parent_id, menu_name, path, permission权限标识如employee:addsys_user_role用户角色关联表user_id, role_id多对多关系sys_role_menu角色菜单关联表role_id, menu_id多对多关系employee员工信息表id, emp_no, name, dept_id, position, phone, email, entry_date人事档案的核心表department部门表id, parent_id, dept_name, leader_id, sort树形结构支持多级部门attendance考勤记录表id, emp_id, work_date, sign_in_time, sign_out_time, status每天一条记录salary薪资记录表id, emp_id, month, basic_salary, bonus, deduction, final_salary每月一条记录leave_request请假申请表id, emp_id, leave_type, start_time, end_time, reason, status审批流程用这里特别要指出一个容易被新手搞混的设计点sys_user用户表和employee员工表是拆开的。这个设计的意义在于用户账号是登录系统的凭证员工是真实的人员档案。以后做系统扩展的时候比如要对接企业微信、飞书、钉钉或者未来要把这套系统开放给外部协作人员用户和员工解耦能避免极度痛苦的字段功能冲突。2.2 RBAC权限模型落地方案这套源码的权限模型用的是经典的RBACRole-Based Access Control加了菜单/权限两层的控制粒度。简单解释一下它的工作流程用户登录成功后系统从数据库查出该用户的所有角色再通过角色查出对应的菜单权限列表。后端接口上写PreAuthorize(hasAuthority(employee:add))这种注解Spring Security在方法调用前自动校验当前用户是否有这个权限标识。前端会根据返回的菜单列表动态生成侧边栏没有权限的菜单压根不会出现在页面上。同时在路由守卫里也对页面跳转做二次校验防止用户手动拼url绕过前端限制。这种“后端接口鉴权 前端菜单显隐 前端路由守卫”的三层防护在正规企业项目里已经属于很不错的安全设计。后端永远是最后的底线前端只是提升用户体验的手段。2.3 表设计中的几个坑我看到太多学生项目里的用户表直接包含头像、手机号、角色、部门、工资、考勤一张表塞了几十个字段设计上极度混乱。这份源码实际开发中也走过弯路有两张表的处理方式值得单独拿出来说。部门表用的是parent_id自关联实现树形结构没有用path字段做冗余存储。好处是改动一个部门节点只需要更新一行数据坏处是查询某个子树时需要递归。在实际开发中像这种部门层级基本不会太深一般也就三四层直接用递归查询就好。如果真要优化可以加一个ancestors字段存储所有祖先节点的id查询时用find_in_set直接SQL搞定。考勤表的去重方案也有讲究一位员工一天只能有一条考勤记录所以表上建了emp_id work_date的联合唯一索引。这个设计看似简单但在实际项目中很多人会忘记结果就是重复打卡产生脏数据报表怎么都算不对排错排到怀疑人生。3. 后端核心模块实现3.1 统一返回结构与异常处理前后端分离项目接口联调是日常工作中最频繁的动作。如果每个接口返回的数据格式都不统一前端就不得不针对每个接口单独做容错处理代码丑得没法看。这份源码在common包下定义了一个统一的返回结构public class ResultT { private Integer code; // 200成功500失败401未认证 private String message; // 提示信息 private T data; // 响应数据 }所有Controller的返回值都包成这个结构前端axios封装就可以在拦截器里统一处理code和message遇到401统一跳转登录页不用每个页面都重复写错误弹窗逻辑。这个设计我觉得是所有中大型项目的必备基础设施越早统一越舒服。很多人的项目在service层抛出异常后直接把堆栈信息返回给前端非常不专业。这套源码里定义了一个全局异常处理器用RestControllerAdvice注解拦截所有Controller层抛出的异常统一转换成Result格式返回。同时还有一套自定义的业务异常类BusinessException业务逻辑中遇到参数非法、数据冲突等问题直接throw new BusinessException(员工编号已存在)前端就能拿到友好提示而不会看到一串看不懂的error信息。3.2 JWT认证与Spring Security整合人事管理系统里的薪资数据属于敏感信息安全性要求比较高。这套源码用的是目前应用最广的方案Spring Security JWT。JWT本身是无状态的token机制服务端不保存会话信息客户端每次请求把token放在Header里服务端验签通过就放行特别适合前后端分离和水平扩展的场景。核心流程是这样的用户输入用户名密码登录后端校验成功后来生成JWT tokenexpire时间设置为2小时响应给前端并存储在Vuex和localStorage里。前端axios请求拦截器在每次请求时自动从localStorage取出token放进Authorization: Bearer token请求头。后端有一个JWT认证过滤器每次请求进来先解析token验证通过后把用户信息放入SecurityContext相当于手动帮用户完成了“登录”这个动作。这里有个细节值得提醒一下JWT的密钥管理千万别硬编码写在代码里最好放在配置文件里并且配置在环境变量中。否则源码一旦泄露在Github上任何人只要拿到密钥就能伪造token数据库里的工资单就相当于裸奔了。我在自己的项目里一般用JWT工具类从配置中心读取密钥同时设置了密钥轮换机制2到3个月换一次虽然成本高一点但安全性有保证。Spring Security的配置类是这个模块的“心脏”需要手动放行登录接口、获取验证码接口等白名单的路径其余接口全部进入Security的过滤器链。配置不当的话最常见的问题就是登录接口被Security拦截导致无法登录或者某些不需要权限的静态资源也要求token。这份源码在SecurityConfig里用了一个白名单数组来管理放行路径后续增加新功能需要放行新的接口时在这个数组里加一行就好维护成本极低。3.3 员工管理核心接口实战员工管理模块是整个人事管理系统的核心业务接口也是最多的。从这个模块的代码实现里能学到很多通用性很强的写法。拿最典型的分页查询接口来解剖前端传当前页码、每页条数、查询条件姓名、部门、入职时间范围后端整合成查询参数最终返回分页数据结构PostMapping(/page) PreAuthorize(hasAuthority(employee:list)) public ResultPageResultEmployeeVO getEmployeePage(RequestBody EmployeeQueryDTO query) { PageEmployee page new Page(query.getPageNum(), query.getPageSize()); // LambdaQueryWrapper实现动态条件查询 LambdaQueryWrapperEmployee wrapper new LambdaQueryWrapper(); if (StringUtils.hasText(query.getName())) { wrapper.like(Employee::getName, query.getName()); } if (query.getDeptId() ! null) { wrapper.eq(Employee::getDeptId, query.getDeptId()); } if (query.getEntryDateStart() ! null) { wrapper.ge(Employee::getEntryDate, query.getEntryDateStart()); } employeeMapper.selectPage(page, wrapper); return Result.success(convertToPageResult(page)); }这里用了MyBatis Plus的LambdaQueryWrapper相比字符串写字段名的方式类型安全、支持代码跳转、重构时不容易出错是现在的主流写法。员工表的常用查询场景里还有一个必须掌握的查询员工时关联查出部门名称而不是只返回一个dept_id让前端自己去查字典。这涉及到VO视图对象和DTO数据传输对象的运用。Employee实体类是数据库一对一映射而前端页面上展示的员工列表需要额外携带deptName字段如果用实体直接返给前端要么前端多一次查询要么用临时Map塞字段最后代码越来越没法看。规范的写法是定义EmployeeVO在service层把employee和deptName组装好后再返回。源码里还有一个很实用的功能员工信息Excel导入导出。导入时用EasyExcel读取Excel文件先校验必填项、再逐行校验数据合法性比如身份证号位数、手机号格式把错误行汇总后生成错误报告。导出时把查询结果写入Excel响应给前端下载。这个功能在人事系统的日常使用频率非常高建议各位拿到源码后一定要仔细读一遍Excel工具类的那部分。4. 前端核心模块实现4.1 Vue项目搭建与目录规范看前端这部分之前先默认你已经了解了Vue的基础语法如果Vue实例、组件、指令这些概念都还不熟建议先学完Vue基础再来看这套源码。这套源码使用Vue CLI构建配合Vue Router做路由管理、Vuex做全局状态存储、Axios做HTTP请求。Element UI作为UI组件库是国内做后台管理系统时当之无愧的首选表格、表单、树形控件、日期选择器这些组件稳定可靠遇到问题基本一搜就有解决方案。前端的api目录按后端Controller模块做了拆分每个模块一个JS文件例如employee.js、salary.js、attendance.js每个文件里统一导出接口函数。这样做的目的是当后端接口变了比如从/employee/page改成了/employee/list前端只需要改这一个文件的这一行代码所有引用这个接口的页面自动生效不需要每个页面翻出来改一遍。4.2 Axios封装与接口对接axios如果直接裸用每个页面都要处理loading、错误提示、token注入、401跳转代码会非常冗余。这套源码在utils/request.js里把axios做了一层标准封装所有请求统一走这个封装。// 请求拦截器 service.interceptors.request.use(config { const token getToken() if (token) { config.headers[Authorization] Bearer token } return config }) // 响应拦截器 service.interceptors.response.use( response { const res response.data if (res.code ! 200) { Message.error(res.message || 请求失败) if (res.code 401) { // token失效跳转登录页 store.dispatch(user/logout) router.push(/login) } return Promise.reject(new Error(res.message)) } return res.data }, error { Message.error(error.message || 网络异常) return Promise.reject(error) } )这么封装后在页面里调用接口就极度简洁。比如员工列表页的核心代码const res await getEmployeePage(queryParams) this.employeeList res.records this.total res.total一行请求一行赋数据逻辑清晰测试也好写。而所有的loading动画、错误提示、token失效处理都收敛在拦截器里统一处理掉了。4.3 员工管理页面实战与权限控制页面实现上员工管理页是典型的三段式结构顶部搜索区、中部表格区、底部操作区。这个页面几乎涵盖了所有后台管理页面的核心模式代码结构非常值得新手反复学习。员工列表的核心实现就是加了一个分页组件el-pagination配合一个查询表单数据源由接口实时驱动。页面代码并不复杂真正大家容易忽略的是权限控制的实现细节。前端权限的实现这套源码结合了动态路由和自定义指令。动态路由的逻辑是用户登录后通过/auth/menus获取该用户可见的菜单列表然后通过router.addRoutes()动态添加路由表。这样做的直接效果是普通员工登录后侧边栏只会出现个人信息、我的考勤、我的薪资而部门管理和员工管理等菜单根本不会出现在页面上。但是前端菜单隐藏仅仅是从UI层面做了限制并不能真正挡住越权访问。所以源码里还有一个Vue自定义指令v-permission用于页面内按钮级别的权限控制el-button v-permissionemployee:add typeprimary clickhandleAdd新增员工/el-button用户没有employee:add这个权限标识组件就会把这个按钮从DOM中移除。这样HR登录能看到“新增员工”按钮普通员工登录连这个按钮都看不到前后端的双重控制才算做到位。5. 项目部署与源码启动指南5.1 前端构建与部署拿到了这套源码第一步当然是把它跑起来。前端部分先确保本机已安装Node.js 14版本和npm。进入hrms-web目录依次执行以下命令npm install npm run servenpm install首次执行可能需要一些时间如果下载速度极慢可以切换淘宝镜像源。启动成功后浏览器访问http://localhost:8080就能看到登录页面。生产环境部署就更讲究一些。先用npm run build打包生成dist静态文件。在Nginx的server配置里需要做两个关键配置首先是静态资源路由把所有前端静态文件指向dist目录。其次需要配置一个location处理API反向代理server { listen 80; server_name yourdomain.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; # 处理history路由刷新404问题 } location /api/ { proxy_pass http://127.0.0.1:8081/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }try_files $uri $uri/ /index.html;这个配置必须写否则使用前端history路由时用户刷新某个子页面就会报404。5.2 后端部署与环境配置后端部署前先要确认本机环境JDK 1.8、Maven 3.6、MySQL 5.7。首先执行源码中的SQL脚本把数据库表结构和初始化数据导入MySQL。然后在application.yml中修改数据库连接、Redis连接如果系统用了Redis做缓存以及JWT密钥配置。本地运行后端直接在IDE中启动HrmsApplication.java主类即可。使用IDEA开发工具时有一个小坑首次导入Maven项目依赖下载特别慢需要检查Maven是否配置了阿里云镜像。另外Java版本必须和pom.xml中配置的版本一致SpringBoot 2.7版本对应JDK 8或11都可以但是如果你用的是JDK 17一些老版本的依赖会有兼容性问题。生产环境部署时一般打成jar包用systemd管理或直接用nohup后台运行mvn clean package -DskipTests nohup java -jar hrms-server.jar --spring.profiles.activeprod /var/log/hrms.log 21 后端启动后可以通过curl做一个简单的健康检查确认接口能正常响应。5.3 快速启动自查清单很多同学拿到源码后跑不起来其实问题集中在少数几个点上。我整理了一份启动自查清单出现问题的时候逐项排查效率会高很多数据库账号密码是否与application.yml中的配置一致MySQL版本是否5.7及以上字符集是否为utf8mb4SQL脚本是否完整执行是否有某个表因为外键依赖执行失败前端.env文件里的接口地址是否指向正确的后端地址后端启动时端口是否被占用默认端口8081可以改成其他端口如果使用Nginx代理代理的请求头是否做了正确的跨域配置如果开发环境是直接请求后端那么后端是否开启了CORS跨域配置6. 开发踩坑记录与经验总结6.1 前后端联调中最常遇到的三类问题开发过程中后端明明联通了前端跑不起来或者数据加载失败这类问题占据了联调阶段70%的排查时间。我在这套源码的实际使用中遇到了不少问题挑三个最典型的分享出来。跨域问题。前端跑在8080端口、后端跑在8081端口浏览器出于同源策略限制会让所有请求直接挂掉控制台报CORS错误。解决方案是后端全局配置跨域或者前端通过Nginx反向代理规避。开发环境后端配置一个CorsConfig类即可。生产环境直接用Nginx反代解决这也是我推荐的方式。日期格式不一致。后端返回的时间是2024-05-20T10:30:00这种ISO格式前端Element UI的日期选择器要的是2024-05-20两边的期望值对不上在考勤和入职日期这些字段上就会展示成一串乱码。解决方案是在后端的实体类日期字段上加JsonFormat注解或者在前端统一做格式化处理。实体类字段与数据库字段命名映射问题。MyBatis Plus默认开启驼峰转换比如数据库字段emp_no能自动映射到实体类属性empNo。如果关闭了这个配置或者字段拼写不匹配查出来的数据全是null又难排查又让人崩溃。强烈建议在application.yml中明确开启驼峰映射配置同时写SQL时不要偷懒少起别名。6.2 权限系统过度设计的翻车教训在很多人的想象中权限系统越复杂越高级结果就是开发到一半被自己设计的权限体系搞到崩溃。这份源码实际上经历过一次“去肥胖化”的重构最初的版本支持多租户用户组岗位权限数据权限范围几十张表互相牵制代码里全是if嵌套。后来彻底精简回到了标准的RBAC模型只保留用户-角色-菜单的经典三件套外加数据权限范围控制在service层实现项目直接轻盈了几倍。给各位一个建议权限系统的设计永远遵循最简单的原则。如果项目没有明确的多租户需求标准RBAC完全够用。等业务发展到真正需要那种灵活度时再逐步迭代而不是一开始就规划一个庞然大物。6.3 项目二次开发建议这套源码的完整度已经很高你可以用它作为毕业设计直接提交但更推荐把它当作一个平台骨架来二次开发。几个方向供参考接入企业微信/钉钉/飞书的通讯录同步让员工信息自动从IM平台同步到人事系统增加审批流引擎把请假、加班、报销的审批流程做成可配置的流程模板现在网上有很成熟的开源工作流引擎比如Flowable可以集成进来增加自动排班和考勤报表功能现在很多公司对弹性工作制的需求越来越多把薪核算和个税计算做成自动化的计算引擎减少HR月末一键处理的时间成本我自己在实际开发中的体会是这种综合管理系统最大的挑战永远不在单点技术难点而是如何在业务复杂度和代码可控性之间保持平衡。读完这套源码、把项目从头到尾跑通一次你对SpringBootVue这套技术栈在企业应用中的理解会从“会写增删改查”提升到“能独立设计一套完整系统”的层次。值得投入时间。本文还有配套的精品资源点击获取
返回列表