Spring Boot + Vue前后端分离企业工资管理系统实战
发布时间:2026/9/24 23:38:34来源:尧图网络
做企业级前后端分离项目很多人一开始就在技术选型上犯了难。如果是课程设计、毕业设计或者中小型公司内部管理系统Spring Boot Vue 这套组合确实是目前最稳、资料最全、上手最快的方案。这次要分享的项目就是一套完整的企业工资管理系统基于 Spring Boot 做后端接口Vue 做前端页面代码、数据库脚本和项目文档三件套齐活拿来即用或者二次开发都很方便。这套系统解决的核心问题是把企业里每月一次、涉及多部门多岗位、容易算错对不上的工资核算流程从 Excel 手工表变成线上流程化操作。管理员配置好工资结构财务录入或导入数据系统自动算税、算实发员工登录能看到自己的工资条整个过程有角色权限控制每一笔操作都有迹可循。它覆盖了工资管理中最常见的需求适合拿来做 Java 课程设计、毕业设计也适合刚接触前后端分离开发的程序员当练手项目甚至可以直接改改作为公司内部的小系统用。1. 系统整体设计与技术选型思路1.1 为什么是 Spring Boot Vue这个问题在项目里被问过无数次了。如果你去翻各种招聘 JDJava 后端岗位基本都写着 Spring Boot前端岗位基本都写着 Vue。技术选型跟着主流生态走最大的红利就是遇到问题能搜到答案。Spring Boot 解决了传统 SSM 项目里大量的 XML 配置问题内嵌 Tomcat打 jar 包就能跑不用单独装服务器这对学生项目和中小型企业内部工具来说太友好了。Vue 的响应式数据绑定和组件化开发让页面写起来效率高而且 Vue 的中文文档和社区教程非常完善学起来成本低。再说前后端分离这件事。传统 JSP 项目是把页面和后端逻辑揉在一起改个页面样式都可能要重启整个应用。前后端分离之后前端工程独立部署用 Nginx 或者随便一个静态服务器就能跑后端只负责提供 JSON 数据接口两边各自开发、各自测试、各自扩展。对团队协作来说这种模式也方便并行开发前端不用等后端写完才能联调提前 Mock 数据就行。1.2 系统功能模块拆解在设计这套工资管理系统的时候我按照基础数据 - 业务处理 - 统计查询 - 权限控制这条主线来拆功能整个系统的功能模块如下表模块核心功能涉及角色登录认证用户名密码登录、JWT令牌签发、退出登录所有用户员工管理员工信息增删改查、按部门筛选、离职状态管理管理员部门管理部门树形结构、部门负责人设置管理员工资项目管理配置基本工资、岗位工资、绩效、补贴、扣款等工资项管理员工资核算按工资项公式计算应发工资、个税、实发工资财务人员工资审核财务提交审核、管理员审核通过/驳回管理员工资查询按月查询员工工资明细、部门工资汇总员工/财务/管理员导入导出Excel模板下载、工资数据批量导入、工资表导出财务/管理员统计报表月度工资总额趋势、部门工资占比、个税统计管理员这个功能清单不是拍脑袋定的而是从实际业务里提炼出来的。工资核算流程通常是每月初 HR 或财务拿到考勤和绩效数据录入系统或者用 Excel 导入系统按配置好的工资项自动计算出每个人的应发工资然后按个税规则计算个人所得税最后得出实发工资。这个过程数据量大、公式多用系统来做既不容易算错又留了操作日志员工有疑问也能追溯。1.3 项目目录结构规划后端我用的经典分层结构包名用com.enterprise.salary作为基础包下面按照 controller、service、mapper、entity、common 来划分src/main/java/com/enterprise/salary/ ├── controller/ # 接口层接收前端请求 │ ├── AuthController.java │ ├── EmployeeController.java │ ├── SalaryController.java │ └── StatisticsController.java ├── service/ # 业务逻辑层 │ ├── impl/ │ │ ├── EmployeeServiceImpl.java │ │ ├── SalaryServiceImpl.java │ │ └── UserServiceImpl.java │ └── ... ├── mapper/ # 数据访问层MyBatis接口 ├── entity/ # 数据库实体类 ├── common/ # 统一返回结果、异常处理、工具类 │ ├── Result.java │ ├── JwtUtil.java │ ├── GlobalExceptionHandler.java │ └── ... ├── config/ # 配置类如MyBatis、拦截器、CORS │ ├── WebMvcConfig.java │ └── MybatisPlusConfig.java └── SalaryManagementApplication.java前端我用 Vue CLI 创建工程也可以用 Vite目录结构如下src/ ├── api/ # axios请求封装 │ ├── request.js │ ├── auth.js │ └── salary.js ├── router/ # 路由配置 │ └── index.js ├── store/ # Vuex状态管理 │ └── user.js ├── views/ # 页面组件 │ ├── Login.vue │ ├── Dashboard.vue │ ├── employee/ │ ├── salary/ │ └── system/ ├── components/ # 公共组件 ├── utils/ # 工具函数 └── App.vue这个结构对中小型项目来说是够用的不会过度设计每个层次职责清晰。初学者看一遍代码就能明白请求从页面到数据库的完整链路Vue 组件调用 API 封装层axios 发起 HTTP 请求到后端 ControllerController 调 Service 处理业务逻辑Service 调 Mapper 访问数据库数据原路返回。2. 数据库设计与核心表结构2.1 数据库整体设计思路数据库我用的 MySQL 8.0字符集选的 utf8mb4排序规则 utf8mb4_general_ci。选 utf8mb4 是因为它能存四字节的 emoji 字符和一些生僻字不怕员工姓名里出现特殊字符。这套系统的表不算多核心就 8 张但每张表的设计都考虑了实际业务的扩展性。先看完整的表清单表名说明关键字段sys_user系统用户表用户名、密码、角色IDsys_role角色表角色编码、角色名称sys_user_role用户角色关联表用户ID、角色IDemp_employee员工信息表工号、姓名、部门ID、岗位、入职日期emp_department部门表部门名称、上级部门IDsal_salary_item工资项配置表项目名称、类型加项/减项、是否启用sal_salary_record工资记录表员工ID、月份、各项工资、应发、个税、实发sal_salary_audit工资审核记录表工资记录ID、审核人、审核状态、审核意见这里有个设计上的取舍值得说一说工资项和工资记录是分开的。工资项是模板配置了基本工资、绩效、餐补、五险一金个人缴纳等都有哪些工资记录是实例每个月员工实际发工资时系统把各项的具体金额存储下来。这么设计的好处是以后增加一个工资项比如高温补贴只需要在配置表里加一条记录历史工资数据不受影响。如果你把工资项字段直接加在工资记录表里当列用每增加一个工资项就要改表结构这在线上环境是很麻烦的事所以我宁可多设计一张表也不图省事把列写死。2.2 核心表结构说明员工表是最基础的数据来源设计上要注意工号唯一、部门外键关联。表结构的关键代码如下CREATE TABLE emp_employee ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, emp_no varchar(32) NOT NULL COMMENT 员工工号, emp_name varchar(64) NOT NULL COMMENT 员工姓名, gender tinyint(1) DEFAULT NULL COMMENT 性别1-男0-女, dept_id bigint(20) DEFAULT NULL COMMENT 部门ID, position varchar(64) DEFAULT NULL COMMENT 岗位, phone varchar(20) DEFAULT NULL COMMENT 手机号, email varchar(128) DEFAULT NULL COMMENT 邮箱, entry_date date DEFAULT NULL COMMENT 入职日期, leave_date date DEFAULT NULL COMMENT 离职日期, status tinyint(1) DEFAULT 1 COMMENT 状态1-在职0-离职, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_emp_no (emp_no), KEY idx_dept_id (dept_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT员工信息表;工号要建唯一索引这个不用多说企业里工号就是员工的唯一标识。部门ID建普通索引是因为查询某部门的所有员工是个高频操作比如财务部有哪几个人要发工资这类场景走索引比全表扫描快得多。工资记录表是业务核心设计时要考虑按月份查询和按员工查询两个高频场景CREATE TABLE sal_salary_record ( id bigint(20) NOT NULL AUTO_INCREMENT, employee_id bigint(20) NOT NULL COMMENT 员工ID, salary_month varchar(7) NOT NULL COMMENT 工资月份格式2025-06, base_salary decimal(10,2) DEFAULT NULL COMMENT 基本工资, post_salary decimal(10,2) DEFAULT NULL COMMENT 岗位工资, performance decimal(10,2) DEFAULT NULL COMMENT 绩效工资, allowance decimal(10,2) DEFAULT NULL COMMENT 补贴, overtime_pay decimal(10,2) DEFAULT NULL COMMENT 加班费, social_insurance decimal(10,2) DEFAULT NULL COMMENT 五险个人缴纳, housing_fund decimal(10,2) DEFAULT NULL COMMENT 公积金个人缴纳, tax decimal(10,2) DEFAULT NULL COMMENT 个人所得税, gross_salary decimal(10,2) DEFAULT NULL COMMENT 应发工资, net_salary decimal(10,2) DEFAULT NULL COMMENT 实发工资, status tinyint(1) DEFAULT 0 COMMENT 状态0-核算中1-待审核2-已通过3-已驳回, create_by bigint(20) DEFAULT NULL COMMENT 创建人, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_salary_month (salary_month), KEY idx_employee_id (employee_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT工资记录表;工资使用 decimal 而不是 float/double这是很多初学者容易踩的坑。float 和 double 是浮点数存 0.1 这种数在二进制里是无限循环的算工资这种对精度要求极高的场景很小的误差累积起来也会出大问题。decimal(10,2) 表示最多存 10 位数字其中小数占 2 位企业工资场景完全够用。2.3 关键索引与外键设计经验外键这个事在设计时到底建不建行业内有两种看法。我这套系统的做法是不建物理外键只建逻辑外键。也就是说表结构里不写 FOREIGN KEY 约束但保留业务含义的关联字段比如 employee_id 指向员工表主键。原因是物理外键在数据量上来之后会影响插入性能而且删除数据时容易受到约束限制尤其是工资记录这类数据不能允许员工被随意删除导致历史工资丢失。逻辑外键配合代码层面校验灵活性更高。索引设计方面我遵循一个原则只为高频查询的字段建索引不为所有字段建索引。工资记录表里 salary_month 和 employee_id 必须建索引因为系统里查某月所有人查某人所有月份这两个查询是最频繁的。组合索引 idx_employee_month (employee_id, salary_month) 也可以建覆盖某个员工某个月的工资这种查询。但不要在 status 这种区分度低的字段上建索引工资状态就那么几个值建了索引 MySQL 也大概率不走白占空间。数据库脚本文件里我额外提供了初始化数据包括一个管理员账号和演示用的几个部门、员工数据方便拿到项目后第一时间能看到效果不用自己手动录数据。3. 后端核心模块实现3.1 统一返回接口与全局异常处理前后端分离项目里接口返回的数据格式一定要统一不然前端每个页面都要单独处理各种特殊情况代码会非常难看。我定义了一个 Result 类作为所有接口的统一返回格式public class ResultT { private Integer code; // 状态码200-成功401-未登录403-无权限500-失败 private String message; // 提示信息 private T data; // 数据 public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(操作成功); result.setData(data); return result; } public static T ResultT error(Integer code, String message) { ResultT result new Result(); result.setCode(code); result.setMessage(message); return result; } }前端 axios 封装里统一判断 code等于 200 就走成功逻辑否则弹出 message 提示。这样后端不管遇到什么业务异常只要抛出一个自定义异常全局异常处理器就能统一捕获并返回固定格式的 JSON不会出现后端报错前端拿到一堆看不懂的堆栈信息的情况。全局异常处理这块我自定义了 BusinessException 类用于业务逻辑中主动抛出异常然后用 RestControllerAdvice 做统一拦截。拦截器里捕获三类异常参数校验异常Valid 校验不通过、业务异常、系统异常。这么做的好处是Service 里不用到处写 try-catch只要在关键节点抛出异常异常信息就能以统一格式返回给前端。3.2 基于 JWT 的登录认证与权限控制工资系统有明确角色分工不能随便谁登录就能看到所有员工工资。这里我用了主流方案Spring Security JWT。登录接口校验用户名密码验证通过后生成 token 返回前端前端把 token 存在 localStorage 里每次请求在请求头加 Authorization: Bearer 。后端用一个拦截器或者过滤器校验 token 有效性没有 token 或 token 过期直接返回 401。JWT 实现的核心代码片段Component public class JwtUtil { // 实际项目中密钥应该配置在application.yml里不要写死在代码中 Value(${jwt.secret}) private String secret; Value(${jwt.expiration}) private Long expiration; public String generateToken(Integer userId, String username, String role) { Date now new Date(); Date expireDate new Date(now.getTime() expiration * 1000); return Jwts.builder() .setSubject(username) .claim(userId, userId) .claim(role, role) .setIssuedAt(now) .setExpiration(expireDate) .signWith(SignatureAlgorithm.HS256, secret) .compact(); } public Claims parseToken(String token) { return Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); } }权限控制我用注解方式实现在 Controller 方法上加 PreAuthorize(hasRole(ADMIN)) 这种注解由 Spring Security 统一判断当前用户是否有权限访问。这样代码可读性很好不看逻辑实现也知道这个接口谁可以调。这里有个实操要点JWT 存在服务端无法主动失效的问题比如员工离职了要立刻收回权限但因为 token 没过期他还能调接口。解决方案是给 token 设置较短的过期时间比如 2 小时同时后台在用户表中维护一个 token 版本号JWT 里带上版本号每次请求校验版本号是否一致不一致就强制重新登录。这个方案不算复杂但在实际项目中非常实用。3.3 工资计算与审核流程实现工资计算这块是这套系统里业务逻辑最核心的部分。计算规则是这样的应发工资 基本工资 岗位工资 绩效 补贴 加班费实发工资 应发工资 - 五险个人缴纳 - 公积金个人缴纳 - 个人所得税。个税计算我实现了简化版的累进税率算法按照年度累计预扣法计算。不过课程设计场景下我默认用月度简化方式演示——先把每个月当独立周期按 5000 元起征点计算public BigDecimal calculateTax(BigDecimal taxableIncome) { if (taxableIncome null || taxableIncome.compareTo(BigDecimal.ZERO) 0) { return BigDecimal.ZERO; } // 简化版个税计算实际操作应按年度累计预扣法 BigDecimal tax BigDecimal.ZERO; if (taxableIncome.compareTo(new BigDecimal(3000)) 0) { tax taxableIncome.multiply(new BigDecimal(0.03)); } else if (taxableIncome.compareTo(new BigDecimal(12000)) 0) { tax taxableIncome.multiply(new BigDecimal(0.10)) .subtract(new BigDecimal(210)); } else if (taxableIncome.compareTo(new BigDecimal(25000)) 0) { tax taxableIncome.multiply(new BigDecimal(0.20)) .subtract(new BigDecimal(1410)); } // ... 更多档位省略 return tax.setScale(2, RoundingMode.HALF_UP); }工资审核流程我是用状态机来管理的。工资记录从核算中 - 待审核 - 已通过 / 已驳回每一次状态流转都在审核记录表里写一条审计日志记录谁在什么时间做了什么操作。为什么要保留这个审计功能因为工资是敏感数据一旦员工对工资有疑问监管方或公司管理层需要知道每一笔审核操作是谁做的这是企业级系统的基本要求。3.4 使用 EasyExcel 实现工资数据导入导出每个月财务手头可能已经有一份 Excel 考勤绩效表了如果系统还要人一条条录进去就太傻了。所以我集成了阿里开源的 EasyExcel 来做批量导入导出。导出功能实现思路先查询出指定月份的工资数据然后用 EasyExcel 的写操作生成一个临时文件通过 HTTP 响应输出流推给前端下载。代码大致是这样GetMapping(/export) public void exportSalary(RequestParam String month, HttpServletResponse response) throws IOException { ListSalaryRecord records salaryService.getByMonth(month); // 转换为导出VO ListSalaryExportVO exportList records.stream().map(record - { SalaryExportVO vo new SalaryExportVO(); BeanUtils.copyProperties(record, vo); vo.setEmpName(record.getEmployee().getEmpName()); return vo; }).collect(Collectors.toList()); response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setCharacterEncoding(utf-8); String fileName URLEncoder.encode(工资表_ month, UTF-8).replaceAll(\\, %20); response.setHeader(Content-Disposition, attachment;filename*utf-8 fileName .xlsx); EasyExcel.write(response.getOutputStream(), SalaryExportVO.class) .sheet(工资明细) .doWrite(exportList); }导入功能我做了模板下载 错误校验。先让用户下载模板按模板填好数据后上传后端逐行校验数据有效性比如员工工号是否存在、工资月份是否重复、金额是否为正数。校验不通过的行收集错误信息一次性返回给前端前端把错误信息解析后逐行标注方便财务快速修正。4. 前端页面搭建与交互实现4.1 Vue 项目初始化与路由配置前端环境需要先装 Node.js我建议用 16 或 18 的 LTS 版本。装好之后用 Vue CLI 创建项目npm install -g vue/cli vue create salary-web创建过程中选择 Vue 3 还是 Vue 2 取决于你的技术基础。如果刚学 Vue建议用 Vue 3 Element PlusComposition API 写起来更清晰而且 Element Plus 组件库对表格、表单、弹窗这些管理后台场景支持很完善。如果学校课程教的是 Vue 2那就用 Vue 2 Element UI两者都行关键是能跑通。创建好工程后需要安装核心依赖npm install axios vue-router4 vuex element-plus路由配置这块我用了懒加载的方式页面多的时候首屏加载速度快很多。路由守卫放在 router.beforeEach 里每次跳转前检查 localStorage 里有没有 token没有就强制跳到登录页router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (to.path /login) { next(); } else { if (!token) { next(/login); } else { next(); } } });4.2 核心页面工资报表、员工管理、权限控制工资报表页面是这个系统的主页。每个人能看到的数据范围由角色决定管理员看全公司所有员工的工资财务看到自己负责的数据普通员工只能看自己的工资条。页面用 Element Plus 的 el-table 展示按月筛选、按部门筛选、导出按钮都在顶部工具栏。表格渲染的时候要注意金额字段的格式化数据库中存的是 decimal返回 JSON 给前端是数字直接展示可能是一长串要统一用 toFixed(2) 格式化成两位小数。这个处理放前端可以做放后端在 VO 层处理也可以。我建议在后端就格式化成字符串返回这样前端展示逻辑更简单也不容易出现浮点数精度问题。员工管理页面相对简单就是常规的增删改查。但有一点要注意员工删除操作在真实业务中通常是逻辑删除就是把状态改成离职而不是物理删除这条记录。因为员工可能关联了很多历史工资记录物理删除了员工表的数据那些历史工资就找不到归属人了。页面里做的是离职按钮而不是删除按钮这个细节和面试官或老师聊起来会很加分。4.3 前端权限控制细节后端有权限控制前端也要做配合。不然菜单和按钮都显示出来用户点了之后才得到无权限的提示体验很差。前端权限控制分两层路由级和按钮级。路由级控制在路由配置里给每个路由加 meta 字段标记需要的角色{ path: /employee, name: Employee, component: () import(/views/employee/Index.vue), meta: { roles: [ADMIN, HR] } }路由守卫里判断用户角色是否在 meta.roles 中不在就跳转 403 页面。按钮级控制是封装一个 v-permission 自定义指令按钮显示还是隐藏根据用户角色决定Vue.directive(permission, { mounted(el, binding) { const requiredRole binding.value; const userRole store.state.user.role; if (requiredRole ! userRole) { el.parentNode el.parentNode.removeChild(el); } } });这样页面代码里写 删除 非管理员用户根本看不到这个按钮从入口上就做了限制。5. 项目文档的编写思路与答辩要点5.1 文档应该包含哪些内容这个项目附带了一份完整的项目文档从需求分析到设计实现到测试部署都有。很多同学做项目重代码轻文档这是错误的思路。尤其是做毕业设计或课程设计文档占据的评分比重非常高。文档的目录结构可以参考下面这版章节核心内容需求分析项目背景、用户角色、功能需求、非功能需求可行性分析技术可行性、经济可行性、操作可行性系统设计架构设计、功能模块设计、数据库设计详细设计核心类设计、接口文档、关键流程图系统实现各模块实现思路、核心代码说明、页面截图系统测试测试用例、测试结果、缺陷修复记录总结与展望项目完成情况、不足之处、改进方向写文档有个技巧先写目录框架再逐节填充内容。很多同学喜欢先写代码再补文档结果写文档时忘了当时的设计思路。我的习惯是开发过程中每完成一个模块就顺手记录要点最后整理成正式文档这样文档质量和开发的真实情况是匹配的。5.2 答辩时容易被问到的问题根据我带过的项目经验答辩环节老师最关注的不是功能有多少而是你到底懂不懂自己写的代码。几个高频提问点要提前准备第一个问题为什么选择 Spring Boot 而不是 SSM要能说清楚 Spring Boot 自动配置、内嵌服务器、起步依赖这些核心特性解决了什么问题。第二个问题数据库为什么这么设计要能说出工资项和工资记录分离的设计考量。第三个问题权限控制是怎么做的要能解释 JWT 的原理、为什么不用 Session。这些问题在文档里都有对应章节关键是答辩时能脱稿、用自己的话讲出来。6. 常见问题与排查技巧实录6.1 部署与启动问题后端项目拿到手后第一步修改 application.yml 里的数据库连接信息确保数据库用户密码正确spring: datasource: url: jdbc:mysql://localhost:3306/salary_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver执行 sql 文件初始化数据库时我遇到过一个问题MySQL 8.0 的 utf8mb4 字符集和排序规则在导入脚本时如果有兼容性警告可能导致部分表建不出来。解决办法是在执行脚本前先执行 SET NAMES utf8mb4;或者直接用 Navicat/DataGrip 这类图形化工具导入不要把 sql 文件里的内容复制粘贴到命令行执行——编码格式很容易出问题。前端启动之前别忘了装依赖npm install npm run serve很多拿到源码的同学直接跳过 npm install 跑 npm run serve然后报出一堆 module not found 的错误。这是新手最容易犯的错误记住前端项目首次运行必须先安装依赖。6.2 跨域与接口联调问题前端跑在 8080 端口后端跑在 8081 端口浏览器常规请求会因为跨域被拦截。解决方案是在后端加一个 CORS 配置类Configuration public class CorsConfig { Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }; } }我遇到过最多的情况是配置了 allowCredentials(true) 但 allowedOrigins 用了 这样在部分浏览器版本下会报错。解决方法是按上面代码用 allowedOriginPatterns() 配合 allowCredentials(true)虽然严格说不算最安全的配置但本地开发和课程设计环节完全够用。如果要上线再收紧跨域策略只允许特定域名访问。6.3 数据精度与计算错误问题工资计算涉及多层加加减减我用的是 BigDecimal但 BigDecimal 也有坑。比如 new BigDecimal(0.1) 和 new BigDecimal(0.1) 的结果是不一样的。前者实际的值是 0.1000000000000000055511151231257827后者才是精确的 0.1。所以在所有从外部传入或字符串转换的场景一律用 new BigDecimal(string) 的方式创建对象不要直接传入 double 值。Money 类工具方法里我特意加了注释提醒后续开发人员注意。还要注意除法运算的精度问题BigDecimal.divide 如果不指定小数位和舍入模式遇到除不尽的情况会抛 ArithmeticException。比如计算个税时除以 100 的情况不多但涉及比例计算时就会遇到。统一用 divide(divisor, 2, RoundingMode.HALF_UP) 传三个参数保证不会因为精度问题崩溃。6.4 开发效率提升小技巧最后分享一个我在这个项目里用得很顺手的小技巧。后端调试时我习惯在 application.yml 里把 MyBatis 的 SQL 日志打开这样每个查询语句和参数都会打印在控制台里排查数据问题非常方便mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl前端调试时npm run serve 启动后浏览器打开控制台的 Network 面板看接口请求的 URL、请求头、响应体前后端联调的大部分问题都能在这里定位。如果接口返回 401先看请求头有没有带 token如果返回 500去看后端控制台有没有打印 SQL 异常和堆栈信息。按照这个思路排查大部分问题都能快速找到根源。我自己刚开始做这类管理系统的时候总是想把功能做得多一点、界面做得炫一点后来才明白企业级系统最重要的是数据准确、流程清晰、权限严密。这套工资管理系统在里面找到的平衡点是功能覆盖完整但不过度设计代码结构清晰便于二次开发数据库设计规范经得起推敲。拿到源码之后建议先把数据库脚本跑起来然后按照登录 - 配置工资项 - 创建员工 - 录入工资 - 审核 - 查询导出这个流程走一遍把主流程跑通之后再去看代码理解起来会快很多。
网站建设高端定制企业官网