这个基于SpringBoot+Vue的工资信息管理系统是我在完成本科毕业论文时的实战项目,前后耗时3个月开发完成。系统主要解决了中小企业工资管理信息化程度低、手工核算效率差、数据安全性弱等痛点。采用前后端分离架构,后端使用SpringBoot+MyBatis实现业务逻辑,前端基于Vue+ElementUI构建交互界面,最终实现了从员工信息管理、工资自动计算到多维报表分析的全流程数字化管理。
在实际开发过程中,我发现很多同学在类似毕业设计项目中容易陷入两个误区:要么过度追求技术复杂度导致项目难以完成,要么功能太过简单缺乏技术亮点。这个项目在技术选型和功能设计上做了平衡,既保证了毕业答辩时的技术深度展示,又控制了整体开发难度。下面我就从技术实现角度,详细拆解这个系统的开发过程。
选择SpringBoot作为后端框架主要基于以下考虑:
Vue.js作为前端框架的优势在于:
技术选型心得:毕业设计不建议盲目追求新技术,应该选择文档丰富、社区活跃的技术栈。我在初期考虑过React+Node.js方案,但发现调试复杂度会显著增加,最终选择了更稳妥的组合。
code复制[前端层] Vue.js + Axios + ElementUI
↓ HTTP请求 ↑ JSON响应
[接入层] SpringBoot RESTful API
↓ 业务处理 ↑ 数据返回
[服务层] 工资计算引擎 + 权限服务
↓ SQL操作 ↑ 结果映射
[持久层] MyBatis + MySQL
↓ 缓存交互 ↑
[缓存层] Redis
关键设计决策:
工资计算是系统的核心难点,需要考虑多种因素:
数据库设计关键表:
sql复制CREATE TABLE `salary_template` (
`id` INT NOT NULL AUTO_INCREMENT,
`template_name` VARCHAR(50) NOT NULL COMMENT '模板名称',
`basic_salary` DECIMAL(10,2) DEFAULT 0 COMMENT '基本工资',
`performance_rate` DECIMAL(5,4) DEFAULT 1.0 COMMENT '绩效系数',
`social_insurance` DECIMAL(5,4) DEFAULT 0.08 COMMENT '养老保险比例',
`housing_fund` DECIMAL(5,4) DEFAULT 0.12 COMMENT '公积金比例',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
核心计算逻辑(Java实现):
java复制public BigDecimal calculate(SalaryCalculateDTO dto) {
// 获取工资模板
SalaryTemplate template = templateMapper.selectById(dto.getTemplateId());
// 基本工资计算
BigDecimal base = template.getBasicSalary();
// 绩效工资 = 绩效系数 × 绩效基数
BigDecimal performance = template.getPerformanceRate()
.multiply(dto.getPerformanceBase());
// 社保扣除 = (养老保险+医疗保险+失业保险) × 基数
BigDecimal insurance = template.getSocialInsurance()
.add(template.getMedicalInsurance())
.add(template.getUnemploymentInsurance())
.multiply(dto.getInsuranceBase());
// 累计预扣法计算个税
BigDecimal tax = TaxCalculator.cumulativeWithholding(
base.add(performance),
dto.getSpecialDeduction(),
dto.getMonth()
);
return base.add(performance)
.subtract(insurance)
.subtract(tax);
}
踩坑记录:初期直接使用减法计算浮点数导致精度丢失,后来改用BigDecimal并设置精度模式:
java复制@Bean public BigDecimalMathContext mathContext() { return new BigDecimalMathContext(2, RoundingMode.HALF_UP); }
采用RBAC(基于角色的访问控制)模型设计:
权限验证流程:
java复制@PreAuthorize("hasRole('HR') or hasRole('ADMIN')")
@PostMapping("/salary/adjust")
public Result adjustSalary(@RequestBody AdjustDTO dto) {
// 调薪逻辑
}
前端权限控制实现:
javascript复制// 在路由守卫中检查权限
router.beforeEach((to, from, next) => {
const roles = store.getters.roles
if (to.meta.roles && !to.meta.roles.includes(roles)) {
next('/403') // 无权限跳转
} else {
next()
}
})
初期使用POI直接导出Excel时,500条数据需要8秒完成,经过以下优化降至1秒内:
java复制// 创建可处理大数据量的工作簿
SXSSFWorkbook workbook = new SXSSFWorkbook(100); // 保留100行在内存中
需求变更时需要保留历史计算规则,采用策略模式+版本号设计:
java复制public interface SalaryCalculator {
String getVersion();
BigDecimal calculate(SalaryCalculateDTO dto);
}
@Service
@CalculatorVersion("2023")
public class SalaryCalculator2023 implements SalaryCalculator {
// 2023年计算规则实现
}
@Service
@CalculatorVersion("2024")
public class SalaryCalculator2024 implements SalaryCalculator {
// 2024年新个税规则实现
}
通过@Resource注解按版本注入不同实现:
java复制@Resource(name = "${salary.calculator.version}Bean")
private SalaryCalculator calculator;
使用JMeter模拟100并发用户:
关键优化手段:
java复制@Cacheable(value = "salary", key = "#employeeId+'_'+#month")
public SalaryDetail getDetail(Long employeeId, String month) {
// 数据库查询
}
sql复制ALTER TABLE salary_detail ADD INDEX idx_emp_month (employee_id, month);
这个毕业设计项目最终获得了92分的优秀成绩,主要得益于以下亮点:
如果继续开发,我会优先实现:
对于正在做类似项目的同学,我的建议是: