1. 项目背景与需求分析
在当今数字化转型浪潮下,企业人力资源管理正经历着从传统纸质化向智能化、移动化的转变。我们团队最近为一家中型制造企业开发了一套基于SpringBoot和微信小程序的绩效薪资管理系统,解决了他们长期存在的几个痛点:
- 绩效数据滞后:原先使用Excel表格手工统计,月底才能出结果
- 薪资计算错误:复杂的奖金公式经常出现人为计算失误
- 员工查询不便:需要到HR部门当面询问个人数据
- 管理层决策缺乏依据:无法实时查看团队绩效趋势
这套系统上线后,实现了:
- 绩效数据实时采集(日/周/月不同维度)
- 自动计算薪资(支持200+自定义计算规则)
- 微信小程序端随时查询
- 多维度数据分析报表
2. 技术架构设计
2.1 整体技术栈选型
经过技术评估,我们最终确定的技术方案如下:
后端核心:
- Spring Boot 2.7.18(LTS版本)
- Spring Security(OAuth2认证)
- MyBatis-Plus 3.5.3(数据访问层)
- Redis 6.2(缓存层)
- Quartz 2.3.2(定时任务)
前端架构:
- 微信小程序原生开发(非uni-app)
- Vant Weapp组件库
- ECharts 5.4.3(数据可视化)
数据库:
- MySQL 8.0(主库)
- 阿里云DRDS(分库分表)
特别说明:没有选择SpringBoot 3.x是因为企业IT环境仍以JDK8为主,且部分依赖库尚未完全兼容。实际测试发现SpringBoot 2.7在性能与稳定性上完全满足需求。
2.2 微服务拆分策略
虽然项目规模中等,但我们仍采用微服务架构设计,主要考虑以下因素:
- 绩效计算服务:独立部署避免影响主业务
- 报表生成服务:资源密集型操作隔离
- 通知推送服务:保证消息可达性
服务间通信采用RESTful API+事件总线(Spring Cloud Stream)混合模式:
- 同步调用:薪资计算结果查询
- 异步事件:绩效数据变更通知
3. 核心功能实现细节
3.1 绩效数据采集模块
数据结构设计:
@Entity @Table(name = "t_performance") public class Performance { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(precision = 5, scale = 2) private BigDecimal score; // 百分制得分 @Enumerated(EnumType.STRING) private Dimension dimension; // 考核维度枚举 @ManyToOne @JoinColumn(name = "employee_id") private Employee employee; @JsonFormat(pattern = "yyyy-MM") private LocalDate cycle; // 考核周期 }关键业务逻辑:
- 支持多种评分模式:
- 上级评分(60%权重)
- 同事互评(30%权重)
- 自评(10%权重)
- 数据校验规则:
@AssertTrue(message = "评分必须在0-100之间") public boolean isValidScore() { return score.compareTo(BigDecimal.ZERO) >= 0 && score.compareTo(new BigDecimal(100)) <= 0; }
3.2 薪资计算引擎
规则配置表设计:
CREATE TABLE `t_salary_rule` ( `id` bigint NOT NULL AUTO_INCREMENT, `rule_name` varchar(50) COLLATE utf8mb4_bin NOT NULL, `expression` text COLLATE utf8mb4_bin NOT NULL COMMENT 'Groovy脚本', `priority` int DEFAULT '0', `active` bit(1) DEFAULT b'1', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;动态脚本执行:
public BigDecimal calculate(SalaryContext context) { GroovyShell shell = new GroovyShell(); shell.setVariable("baseSalary", context.getBaseSalary()); shell.setVariable("performance", context.getPerformanceScore()); Script script = shell.parse(rule.getExpression()); Object result = script.run(); if (!(result instanceof BigDecimal)) { throw new CalculationException("脚本返回值必须是BigDecimal类型"); } return (BigDecimal) result; }实际开发中发现Groovy脚本存在性能问题,最终采用预编译+缓存方案,TPS从50提升到1200+
4. 微信小程序端实现
4.1 登录鉴权方案
采用微信官方登录流程优化版:
- 前端调用wx.login获取code
- 后端用code+appid+secret换取openid
- 生成JWT令牌(包含员工ID)
- 建立会话关联(Redis存储)
安全增强措施:
- 接口签名验证(防止重放攻击)
- 敏感数据脱敏(如薪资只显示后四位)
- 操作日志审计(记录所有查询行为)
4.2 性能优化实践
首屏加载优化:
- 接口数据分级加载:
- 第一优先级:当月薪资概要
- 第二优先级:历史记录
- 第三优先级:分析图表
- 本地缓存策略:
wx.setStorageSync('lastSalary', { timestamp: Date.now(), data: res.data }); - 图片资源CDN加速
实测数据对比:
| 优化措施 | 首屏时间(ms) | 内存占用(MB) |
|---|---|---|
| 原始版本 | 3200 | 158 |
| 优化后 | 980 | 92 |
5. 部署与运维方案
5.1 生产环境配置
服务器规格:
- 应用服务器:2C4G × 3(K8S集群)
- Redis:阿里云版 1G内存
- MySQL:RDS高可用版 4C8G
关键JVM参数:
-server -Xms2g -Xmx2g -XX:MaxMetaspaceSize=512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=4 -XX:ConcGCThreads=25.2 监控体系建设
基础监控:Prometheus + Grafana
- 采集指标:JVM、MySQL、Redis
- 预警规则:GC次数>5次/分钟
业务监控:
- 薪资计算耗时百分位(P99<500ms)
- 每日登录用户数波动预警(±30%)
日志分析:ELK Stack
- 关键日志标记:
@Slf4j(topic = "SALARY_CALC") public class SalaryService { public void calculate() { log.info("[PERF]开始计算薪资,员工ID:{}", employeeId); } }
- 关键日志标记:
6. 踩坑与解决方案
6.1 微信小程序缓存问题
现象:iOS设备上薪资数据不更新根因:小程序默认缓存策略导致解决方案:
wx.request({ url: 'https://api.example.com/salary', header: { 'Cache-Control': 'no-cache', 'Pragma': 'no-cache' }, success(res) { // 处理数据 } })6.2 并发计算问题
现象:月底批量计算时出现死锁根因:MyISAM引擎表锁+事务混合使用最终方案:
- 全部表转为InnoDB
- 采用分段计算策略(每100人一个批次)
- 添加分布式锁(Redisson实现)
RLock lock = redissonClient.getLock("salaryCalcLock"); try { if (lock.tryLock(10, 60, TimeUnit.SECONDS)) { // 执行计算 } } finally { lock.unlock(); }这套系统目前已在客户生产环境稳定运行8个月,支撑了2000+员工的日常绩效考核与薪资管理。开发过程中最深的体会是:企业级系统不仅要考虑功能实现,更需要关注数据一致性、性能瓶颈和异常处理。特别是在薪资这种敏感领域,1分钱的误差都可能引发信任危机。