新闻详情

新闻详情

首页 / 资讯中心 / 详情

SpringBoot+Vue人事管理系统实战:从零搭建前后端分离项目

发布时间:2026/9/27 23:49:30来源:尧图网络
SpringBoot+Vue人事管理系统实战:从零搭建前后端分离项目
简介这份资源是面向高校计算机相关专业毕业生与课程设计学习者的完整人事管理系统项目源码采用SpringBoot与Vue前后端分离架构适合作为毕业设计、课程大作业或全栈练手参考。压缩包共185个文件约2MB其中81个Java文件承载后端RESTful接口与业务逻辑24个Vue组件与29个JavaScript文件构成前端页面与交互另有14个XML配置、SQL建表脚本及字体图标等静态资源结构完整可直接运行。系统覆盖用户认证授权、员工信息管理、组织架构、考勤休假、薪资福利与系统管理等核心模块后端借助Spring Security实现密码加密与权限控制前端结合Element UI与Axios完成数据交互。已有71人学习下载读者可据此掌握前后端分离项目的分层设计、接口联调与数据库建模思路快速搭建可演示的人事管理平台。1. 从一份“人事管理系统.zip”说起SpringBootVue 前后端分离到底交付了什么拿到「基于SpringBootVue实现人事管理系统.zip」这个标题的人大概率处在两种状态之一要么是正在做计算机毕业设计需要一套能跑起来、能答辩、能写进论文的系统要么是刚入行的开发者想找一个业务闭环完整、技术栈主流的练手项目。人事管理系统恰好是这两类人共同的高频选择——它业务边界清晰员工、部门、考勤、薪资、请假数据关系典型一对多、多对多、状态流转又不像电商那样涉及复杂的库存与并发非常适合把 SpringBoot 和 Vue 的整套前后端分离链路走通一遍。这个标题背后真正要交付的不是一堆 Java 文件而是一条完整的工程链路后端用 SpringBoot 提供 REST 接口、做权限校验、连数据库前端用 Vue 做单页应用、调接口、渲染表格和表单中间靠 JSON 和 Token 打通。很多人卡住的地方不是不会写某个接口而是不知道这套东西怎么从零拼起来、参数怎么配、打包后怎么部署、答辩时被问到“前后端怎么交互”该怎么答。这篇就按一线做项目的顺序把这条链路拆开讲清楚让你能照着复现也能看懂每一步为什么这么做。2. 技术选型与工程骨架为什么是 SpringBoot Vue 这套组合2.1 后端选 SpringBoot 而不是 SSM 的理由做人事管理系统这类中小型业务系统后端最常见的做法是 SpringBoot而不是传统的 SSMSpring SpringMVC MyBatis手工配置。原因很实际SSM 需要自己写一堆 XML 和 web.xml光是让项目跑起来就要折腾半天而 SpringBoot 的起步依赖把 Tomcat、Jackson、数据源这些默认配好一个 main 方法就能启动。对于毕业设计这种时间有限、又要保证功能完整的场景少写配置就是少踩坑。具体到人事系统后端要处理的核心是三类事情一是员工、部门、职位这些基础数据的增删改查二是考勤、请假、薪资这类带状态和审批流的业务三是登录鉴权和角色权限。SpringBoot 配合 MyBatis-Plus 能把这三点都覆盖得比较舒服MyBatis-Plus 自带的分页插件和条件构造器能省掉大量重复 SQL。常见做法是 controller 层只做参数接收和返回封装service 层写业务逻辑mapper 层用 MyBatis-Plus 的 BaseMapper 直接继承简单查询连 SQL 都不用写。选型时还要注意版本。热搜里出现过「springboot版本太高」这个说法这不是空穴来风。SpringBoot 3.x 默认要求 JDK 17并且把 javax 包换成了 jakarta很多老教程里的代码直接抄会报错。如果学校机房或自己的电脑装的是 JDK 8就老老实实用 SpringBoot 2.7.x这是 2.x 最后一个稳定版本生态兼容性最好。下面是一个最小可跑的 pom 依赖片段!-- SpringBoot 2.7.x 起步依赖JDK 8 环境首选 -- parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version /parent dependencies !-- Web 层提供 REST 接口和内嵌 Tomcat -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis-Plus省去大量单表 CRUD 的 SQL -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency /dependencies这段依赖里parent 决定了整个 SpringBoot 的版本基线改它等于改全局。mybatis-plus-boot-starter 的版本要和 SpringBoot 版本匹配3.5.x 系列对 2.7.x 支持稳定。MySQL 驱动 8.x 对应 MySQL 8 数据库如果用的是 MySQL 5.7驱动版本要降到 5.1.x否则连接会报时区或 SSL 相关的错。这些版本对应关系是新手最容易忽略、又最容易导致“项目起不来”的地方。2.2 前端选 Vue 的版本与工程化方式前端这边Vue 有两个大版本Vue 2 和 Vue 3。热搜里「vue入门」「vue安装及环境配置」「vue devtools插件下载」这些词说明很多人卡在环境这一步。给毕业设计用的建议是如果追求资料多、报错好搜用 Vue 2 Element UI如果想跟上主流、用组合式 API用 Vue 3 Element Plus。两者都能做人事系统区别主要在写法。Vue 3 的script setup语法更简洁但网上大量老教程是 Vue 2 的 options 写法混着看容易乱。工程化方式上现在基本都用 Vite 而不是 Vue CLI。Vite 启动快、配置少创建项目一条命令# 用 Vite 创建 Vue 3 项目选择 vue 模板 npm create vitelatest hr-frontend -- --template vue # 进入目录安装依赖 cd hr-frontend npm install # 安装路由和请求库人事系统必备 npm install vue-router4 axios element-plus这几条命令做完前端骨架就有了。vue-router 负责页面跳转登录页、员工列表页、考勤页axios 负责调后端接口element-plus 提供表格、表单、分页这些现成组件。这里要注意 npm 源的问题国内网络直接 npm install 经常卡住可以换成国内镜像源再装这是环境配置阶段最常见的翻车点。前后端分离的关键约定是接口格式统一。我一般会让后端所有接口返回同一个结构比如{ code, msg, data }前端 axios 拦截器统一处理 code 不等于 200 的情况。这样前端每个页面不用各写各的判断出错提示也统一。这个约定在项目一开始就要定好中途改会牵动所有页面。2.3 数据库表设计人事系统的核心几张表人事系统的表不用多但关系要理清。核心是员工表、部门表、职位表、用户表登录用、考勤表、请假表、薪资表。员工和部门是多对一员工和职位是多对一用户和员工可以是一对一员工登录或独立管理员登录。下面给出建表的核心字段思路表名关键字段说明sys_userid, username, password, role, emp_id登录账号role 区分管理员和普通员工departmentid, name, manager_id部门manager_id 指向负责人employeeid, name, dept_id, position_id, hire_date, status员工主表status 表示在职/离职attendanceid, emp_id, date, check_in, check_out, status考勤每人每天一条leave_recordid, emp_id, start_time, end_time, reason, status请假status 走审批流salaryid, emp_id, month, base, bonus, actual薪资按月一条设计时有两个坑要提前避开。一是密码不能明文存至少做一次 MD5 加盐答辩时被问到安全性这是加分项。二是删除员工不要物理删除用 status 字段标记离职否则关联的考勤、薪资记录会变成孤儿数据。这两点在后面避坑章节还会展开。3. 后端落地从登录鉴权到员工 CRUD 的接口实现3.1 登录与 Token 鉴权的最小实现人事系统第一个要跑通的接口是登录。流程是前端提交用户名密码后端查库比对成功则生成一个 Token 返回前端存起来之后每次请求带上这个 Token后端校验。Token 方案常见两种JWT 和 Session。前后端分离场景下 JWT 更合适因为服务端不用存会话状态部署多台也不影响。下面是一个基于 JWT 的登录接口核心代码PostMapping(/login) public Result login(RequestBody LoginDTO dto) { // 1. 按用户名查用户 SysUser user userService.getByUsername(dto.getUsername()); if (user null) { return Result.fail(用户不存在); } // 2. 密码比对数据库存的是 MD5 加盐后的值 String inputPwd MD5Util.encrypt(dto.getPassword(), user.getSalt()); if (!inputPwd.equals(user.getPassword())) { return Result.fail(密码错误); } // 3. 生成 JWT载荷放用户 id 和角色 String token JwtUtil.createToken(user.getId(), user.getRole()); // 4. 返回 token 和基本信息前端存 localStorage MapString, Object data new HashMap(); data.put(token, token); data.put(role, user.getRole()); return Result.ok(data); }这段代码里MD5Util.encrypt 的第二个参数是每个用户独立的盐值存在用户表里。盐值的作用是防止相同密码产生相同哈希被彩虹表撞库。JwtUtil.createToken 一般设置过期时间比如 24 小时过期后前端要重新登录。Result 是统一返回封装ok 和 fail 两个静态方法对应成功和失败。Token 校验放在拦截器里做不要在每个 controller 里重复写。SpringBoot 里实现 HandlerInterceptor在 preHandle 方法里从请求头取 Token、解析、把用户信息塞进 ThreadLocal放行或拦截。拦截器要注册到 WebMvcConfigurer 里并排除登录接口和静态资源路径。这一步没配好会出现“登录接口也被拦截导致永远登不进去”的问题。3.2 员工管理接口分页、条件查询与统一返回员工列表是人事系统里最典型的接口涉及分页和条件查询。用 MyBatis-Plus 的分页插件先配置拦截器Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 分页插件指定数据库类型为 MySQL interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }配置好之后service 里查询就很简单public PageEmployeeVO pageQuery(int pageNum, int pageSize, String name, Long deptId) { // 构造分页对象 PageEmployee page new Page(pageNum, pageSize); // 构造查询条件姓名模糊匹配部门精确匹配按入职时间倒序 LambdaQueryWrapperEmployee wrapper new LambdaQueryWrapper(); wrapper.like(StringUtils.hasText(name), Employee::getName, name) .eq(deptId ! null, Employee::getDeptId, deptId) .orderByDesc(Employee::getHireDate); // 执行分页查询 PageEmployee result employeeMapper.selectPage(page, wrapper); // 转成 VO补上部门名称和职位名称 return convertToVO(result); }这里的关键是 LambdaQueryWrapper 的条件拼接like和eq的第一个参数是布尔值只有为 true 时才拼进 SQL这样就能用一套代码同时支持“带条件查”和“不带条件查”。分页插件会自动在 SQL 后面加 limit不用手写。convertToVO 这一步是把员工表里的 dept_id 换成部门名称因为前端表格要显示中文名而不是数字 id这个转换在 service 层做不要丢给前端。统一返回结构建议长这样{ code: 200, msg: 成功, data: {...} }。code 用 200 表示成功其他值表示各类错误。前端 axios 响应拦截器里判断 code不等于 200 就弹提示并 reject这样业务代码里只处理成功分支代码干净很多。3.3 考勤与请假状态流转怎么落到代码里考勤和请假比 CRUD 多了一层状态流转这是人事系统里最能体现业务逻辑的部分。请假流程一般是员工提交 → 待审批 → 管理员审批 → 通过或驳回。状态用数字或枚举表示比如 0 待审批、1 已通过、2 已驳回。提交请假时后端要做几件事校验开始时间早于结束时间、校验该员工这段时间没有重复请假、写入记录并置状态为待审批。审批时只有管理员角色能调这个接口且只能审批待审批状态的记录防止重复审批。这些校验写在 service 层不要只靠前端校验因为接口是可以被直接调用的。考勤这块常见做法是员工每天打卡一次后端根据打卡时间判断是否迟到比如晚于 9:00 算迟到。这里有个容易忽略的点时间比较要用数据库或服务器统一时间不要用前端传的时间否则改一下本地时间就能“不迟到”。统计月度考勤时用 SQL 的 group by 按员工和月份聚合比在 Java 里循环效率高得多。状态流转的代码要写成“只允许合法跃迁”比如待审批只能变成通过或驳回已通过的不能再改。可以在 service 里写一个状态校验方法所有涉及状态变更的地方都调它。这样即使后面加了新状态改动也集中在一处。4. 前端落地Vue 页面、路由与接口联调4.1 路由与权限登录后才能进的页面怎么拦Vue 项目里路由用 vue-router 配置。人事系统一般分两类页面登录页不需要权限和业务页需要登录。做法是在路由的 meta 里加一个requiresAuth: true标记然后用全局前置守卫判断// router/index.js const routes [ { path: /login, component: Login }, { path: /employee, component: EmployeeList, meta: { requiresAuth: true } }, { path: /attendance, component: Attendance, meta: { requiresAuth: true } } ] router.beforeEach((to, from, next) { const token localStorage.getItem(token) // 需要登录且没有 token跳回登录页 if (to.meta.requiresAuth !token) { next(/login) } else { next() } })这段守卫的逻辑是目标路由需要权限且本地没有 Token就重定向到登录页否则放行。注意 Token 存在 localStorage 里刷新页面不会丢但关闭浏览器再打开还在所以退出登录时要手动清除。热搜里「vue路由参数」也是高频问题比如从员工列表点进详情页要传员工 id用router.push({ path: /employee/detail, query: { id } })详情页用route.query.id取query 参数会显示在地址栏刷新不丢适合这种场景。权限还要分角色。管理员能看所有菜单普通员工只能看自己的考勤和请假。做法是登录后把角色存起来菜单渲染时根据角色过滤路由守卫里也可以加角色判断。前端权限只是体验层面真正的权限控制必须在后端接口上做否则改一下前端代码就能越权。4.2 axios 封装与接口联调跨域和统一错误处理前端调后端接口统一用 axios 封装一个 request 实例配置 baseURL、超时时间、请求拦截器和响应拦截器// utils/request.js import axios from axios const request axios.create({ baseURL: /api, // 开发环境走代理生产环境走 nginx timeout: 10000 }) // 请求拦截每个请求自动带上 token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }) // 响应拦截统一处理业务错误 request.interceptors.response.use( res { if (res.data.code ! 200) { ElMessage.error(res.data.msg) return Promise.reject(res.data.msg) } return res.data.data }, err { ElMessage.error(网络异常) return Promise.reject(err) } ) export default request请求拦截器负责带 Token响应拦截器负责统一弹错误提示并剥离外层结构这样页面里const list await request.get(/employee/page)拿到的直接就是 data 部分。开发阶段前端跑在 5173 端口后端跑在 8080直接请求会跨域。解决办法是在 vite.config.js 里配代理// vite.config.js export default { server: { proxy: { /api: { target: http://localhost:8080, // 后端地址 changeOrigin: true, rewrite: path path.replace(/^\/api/, ) // 去掉 /api 前缀 } } } }代理的作用是让浏览器以为请求的是同源地址实际由 Vite 转发给后端从而绕过跨域限制。rewrite 把/api前缀去掉是因为后端接口路径本身不带这个前缀。这个配置只在开发环境生效打包上线后要用 nginx 做同样的转发。4.3 表格与表单Element Plus 在人事系统里的典型用法人事系统页面大多是“上面搜索条件、中间表格、下面分页”的结构Element Plus 的 el-table、el-form、el-pagination 正好覆盖。员工列表页的核心是表格列渲染和操作按钮el-table :datatableData border el-table-column propname label姓名 / el-table-column propdeptName label部门 / el-table-column proppositionName label职位 / el-table-column label状态 template #default{ row } el-tag :typerow.status 1 ? success : info {{ row.status 1 ? 在职 : 离职 }} /el-tag /template /el-table-column el-table-column label操作 template #default{ row } el-button sizesmall clickhandleEdit(row)编辑/el-button el-button sizesmall typedanger clickhandleDelete(row)删除/el-button /template /el-table-column /el-table这里用到了作用域插槽#default{ row }让每行可以自定义渲染比如状态用 el-tag 显示不同颜色操作列放按钮。表格数据来自接口分页组件的 current-page 和 page-size 绑定到响应式变量变化时重新请求。表单新增和编辑通常共用一个弹窗组件用是否有 id 来区分是新增还是编辑这样能省一半代码。表单校验用 el-form 的 rules必填、长度、格式都在这里配提交前调 validate 方法。注意前端校验只是提升体验后端仍要再校验一遍这是安全底线。5. 避坑与排查这套系统最容易翻车的五个地方5.1 跨域报错但代理配了还是 404现象前端请求接口控制台报 404 或 CORS 错误明明配了代理。原因通常是代理的 rewrite 写错或者后端接口路径和前端请求路径对不上。比如前端请求/api/employee/list代理 rewrite 去掉了/api后端实际接口是/employee/list才对如果后端 controller 上还加了RequestMapping(/api)就会变成/api/employee/list路径重复。解决先在后端日志里看实际收到的请求路径再对照前端 baseURL 和 rewrite 规则三者必须能拼出后端真实路径。5.2 打包后刷新页面 404现象开发环境一切正常npm run build 部署到服务器后点进二级页面再刷新就 404。原因Vue 是单页应用路由是前端控制的服务器上并不存在/employee这个真实文件刷新时服务器找不到就报 404。解决在 nginx 配置里加try_files $uri $uri/ /index.html;让所有找不到的路径都回退到 index.html由前端路由接管。这是前后端分离部署的必配项漏了必翻车。5.3 时间字段前后端差 8 小时现象前端提交的日期到数据库里少了一天或差 8 小时。原因MySQL 的时区、JDBC 连接的时区、Java 的时区、前端序列化格式任何一环不一致都会出问题。常见的是 JDBC URL 没配时区默认按 UTC 处理。解决连接串加上serverTimezoneAsia/Shanghai实体类时间字段用JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8)指定序列化时区。这两个地方配好基本就不会再差时间。5.4 删除部门导致员工数据变孤儿现象删掉一个部门后该部门下的员工列表里部门名称显示为空。原因员工表里的 dept_id 指向了一个已经不存在的部门关联查询查不到。解决删除部门前先检查是否还有员工关联有就禁止删除并提示或者用逻辑删除部门标记为已删除但不真删。数据库层面可以加外键约束但很多项目为了灵活不加那就必须在业务层做校验。5.5 密码明文存储被答辩老师追问现象数据库里密码字段一眼能看出是明文或者只是简单 MD5。原因图省事直接存了明文或者用了 MD5 但没加盐。解决用 MD5 加盐每个用户生成独立随机盐值存表里密码存加盐后的哈希。更好的做法是用 BCrypt它自带盐值且计算慢抗暴力破解更强。改造成本不高但安全性和答辩印象分提升明显属于性价比很高的优化。6. 从能跑到能答辩接口文档、打包部署与二次扩展系统能跑起来只是第一步要让它真正拿得出手还得补三件事。第一件是接口文档。答辩时老师常问“你有哪些接口、参数是什么”临时翻代码很被动。用 Knife4j 或 Swagger 在 SpringBoot 里加几个注解就能自动生成在线接口文档每个接口的路径、参数、返回一目了然。加依赖、写个配置类、在 controller 方法上加ApiOperation注解即可成本很低。第二件是打包部署。后端用mvn clean package打成 jarjava -jar xxx.jar就能跑前端npm run build生成 dist 目录丢给 nginx 托管。nginx 里配两段一段指向 dist 目录并加 try_files 回退一段把/api转发到后端端口。这样一台服务器就能同时跑前后端。部署时注意后端配置文件里的数据库地址、密码要改成服务器上的别把本地配置直接传上去。第三件是二次扩展。人事系统的骨架搭好后加功能其实很快。比如加一个“公告管理”后端建表、写 mapper、service、controller前端加路由、页面、调接口半天能完成。想加数据可视化用 ECharts 画部门人数分布、月度考勤统计接口返回聚合数据即可。想加导出 Excel后端用 EasyExcel 写一个导出接口前端点击下载。这些扩展点能让论文的“系统功能”章节更充实也是答辩时的加分项。我自己做这类项目最大的教训是不要一上来就追求功能多先把登录、一个完整的 CRUD、一次部署跑通形成闭环再往上加。很多人的系统烂尾不是不会写某个模块而是从来没完整跑通过一次导致问题越积越多、信心越做越少。先把最小闭环跑通后面每加一个功能都是在这个闭环上叠加心里就有底了。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

磁县网站制作公司选型一文搞懂:改需求慢的3种技术根源 2026/9/28 0:35:20

磁县网站制作公司选型一文搞懂:改需求慢的3种技术根源

磁县网站制作公司选型一文搞懂:改需求慢的3种技术根源 改个按钮颜色,建站公司拖一周才给反馈?这种憋屈感,很多磁县本地企业老板都尝过。别急着骂人,先看看他们用的是啥技术栈。很多“慢”不是态度问题,是技术债压身。本文不聊虚的,直接拆解三种主流建…

阅读更多 →
时尚网站建设到底多少钱?搞定备案不踩坑的报价全解析 2026/9/28 0:35:07

时尚网站建设到底多少钱?搞定备案不踩坑的报价全解析

时尚网站建设到底多少钱?搞定备案不踩坑的报价全解析 刚接了个做服装品牌的单子,老板第一句话就问:“我想做个高大上的时尚官网,到底多少钱?还有,那个ICP备案流程我是一头雾水,怕耽误上线。”…

阅读更多 →
信誉好的广州外贸网站2026最新 2026/9/28 0:34:10

信誉好的广州外贸网站2026最新

避坑指南:3个广州外贸网站实战案例揭秘信誉好的建站逻辑 别再看那些千篇一律的模板站了,真的,太丑且不够用。很多广州做跨境的朋友跟我吐槽,花了几千块做的站,连个像样的询盘都接不住,客户打开看一眼就关掉,觉得这公司不靠谱。我干了十年建站,见过太…

阅读更多 →
3款wordpress群发插件对比评测,告别手动复制粘贴 2026/9/28 0:34:03

3款wordpress群发插件对比评测,告别手动复制粘贴

3款wordpress群发插件对比评测,告别手动复制粘贴 改个需求建站公司拖一周,这种憋屈谁懂?以前我接私单,客户要发100封营销邮件,我盯着浏览器手动填收件人,手都抽筋了。直到我深入研究了几款主流的wordpress群发插件,才发现原来效…

阅读更多 →
重庆白云seo整站优化避坑指南:3档建站报价详解 2026/9/28 0:33:31

重庆白云seo整站优化避坑指南:3档建站报价详解

重庆白云seo整站优化避坑指南:3档建站报价详解 改个需求建站公司拖一周,这种憋屈事谁没经历过?很多在重庆白云片区做本地生意的老板,为了省那点钱选了低价套餐,结果后期改个按钮颜色都要等三天,气得想砸电脑。其实问题不在人,而在你一开始就没把【…

阅读更多 →
百度搜索引擎关键词优化实战:3个免费工具搞定流量与转化 2026/9/28 0:33:31

百度搜索引擎关键词优化实战:3个免费工具搞定流量与转化

百度搜索引擎关键词优化实战:3个免费工具搞定流量与转化 别再用那些一眼假、排版乱、加载慢的模板网站了。客户打开你的官网,3秒内看不到核心价值,直接关页,连注册邮箱的机会都不给。这时候你才意识到, 模板网站太丑不够用…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉