政务人力资源平台:架构复盘与技术要点
项目概述
背景与目标
原有人力资源系统在多部门、多分支机构场景下暴露出 功能割裂、主数据不统一、审批链路冗长 等问题,人力成本与合规风险同步上升。本项目目标是建设一套 一体化的人力资源管理平台,覆盖员工主数据、考勤与排班、假勤、绩效与薪酬、财务对接等全链路,在可配置前提下支撑 差异化制度(班次、假期类型、绩效方案),并为管理侧提供可观测的统计与决策辅助。
个人职责与边界(示例写法,可按实际调整)
负责 前端工程与部分业务域交付(员工域、考勤/排班子域、权限与通用组件),与后端、产品、实施协同完成功能迭代与上线保障;关键技术决策包含 排班与假勤联动消息方案、复杂 RBAC 落地、绩效公式编辑器等。
核心业务域与实现要点
员工全生命周期管理
- 业务目标:入职—在职—离职全周期主数据治理;合同、培训、考试等扩展档案可关联追溯。
- 工程实现:
- Vue3 + 组合式 API 拆分 信息卡片 / 编辑抽屉 / 时间轴 等可复用模块,降低长表单的维护成本。
- Excel 批量导入导出(模板校验、错误行回写)减少运维录入压力。
- 管理驾驶舱:ECharts 等可视化呈现年龄/司龄/学历结构、流失率趋势,服务于编制与留人策略复盘。
示例:司龄分布柱状图(ECharts Option骨架)
// 将后端聚合结果映射为 ECharts option,避免在模板里堆逻辑
export function buildTenureBarOption(buckets: { label: string; count: number }[]) {
return {
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: buckets.map((b) => b.label) },
yAxis: { type: 'value', name: '人数' },
series: [
{
type: 'bar',
data: buckets.map((b) => b.count),
itemStyle: { color: '#5470c6' },
},
],
};
}考勤、请休假与排班
- 业务目标:对接外部考勤源;支持补卡、异常申诉;假勤类型与审批规则可配置;在 班次、请假、调班 约束下生成可发布的月度排班,并支持预览与导出。
- 技术难点与方案:
- 多制度考勤规则:白班/大小夜/中班等规则差异大 → 抽象 可配置规则模型(时段、宽限、取整策略),前后端共用校验语义,避免「界面能选、后台算错」。
- 假勤/调班与排班一致性:审批通过后若仍按旧版排班执行,易产生合规与加班费争议 → 审批完成事件经 消息队列(RabbitMQ) 推送给责任班组长,触发 排班重算与确认闭环,将「流程结果」与「计划数据」绑定,减少人工二次对齐错误。
示例:审批完成投递消息(Spring AMQP 消费者骨架)
// 消费「假勤/调班已生效」事件,驱动排班域重算(示意,交换机/路由键按实际拓扑配置)
@Component
public class LeaveApprovedConsumer {
@RabbitListener(queues = "${mq.queue.schedule.leave-approved}")
public void onLeaveApproved(LeaveApprovedEvent evt) {
// 1. 幂等:evt.getBizId() 去重或乐观锁
// 2. 标记当月排班表为「待重算」或直接进入领域服务
scheduleRecalculationService.markDirty(evt.getTeamId(), evt.getMonth());
// 3. 通知班组长(站内信 / WS / 推送)
notifyService.notifyTeamLeader(evt.getTeamLeaderId(), evt);
}
}// 前端班组长工作台:订阅通知后刷新排班草稿状态(可与 SSE / 轮询 / WS 配合)
async function refreshScheduleDraft(teamId: string, month: string) {
const { data } = await api.getScheduleDraft(teamId, month);
scheduleStore.replaceDraft(data);
}绩效与薪酬
- 业务目标:指标与公式可配置;按班组加载基础指标并 自动汇总得分与奖金;支持结果确认与申诉;薪酬聚合考勤、绩效、社保公积金及个税逻辑。
- 技术要点:
- 可视化公式编排:基于 Vue 3 拖拽编排 指标、运算符、条件分支,实时生成可持久化的计算表达式(或中间 DSL),降低业务人员依赖开发的频率。
- 重计算路径配合 异步任务 / 队列,避免阻塞在线查询接口。
示例:公式存库(简单版:中缀表达式 + 指标元数据;复杂拖拽可再映射为 AST)
{
"version": 1,
"expr": "(attendance_score * 0.3) + (quality_score * 0.7)",
"metrics": ["attendance_score", "quality_score"]
}复杂场景可将画布 nodes/edges 序列化为 AST / 逆波兰 再存库,由后端沙箱或规则引擎执行;前端负责 可视化编辑 + 依赖校验(禁止循环引用)。
会计台账与对外推送
- 业务目标:薪酬发放结果 自动生成会计台账,按财务要求的周期 定时推送,并具备失败感知与补推能力。
- 工程要点:调度框架驱动批处理;推送链路 脱敏与审计;回调或状态表记录推送结果,支撑对账与重试。
示例:Spring定时任务 + 推送状态机(骨架)
@Scheduled(cron = "${finance.ledger.push-cron}")
public void pushLedgers() {
List<LedgerBatch> pending = ledgerRepository.findPending(LocalDate.now());
for (LedgerBatch batch : pending) {
try {
String payload = maskingService.maskForFinance(batch); // 脱敏
financeClient.push(payload);
batch.setStatus(PushStatus.SUCCESS);
} catch (Exception ex) {
batch.setStatus(PushStatus.FAILED);
batch.setLastError(ex.getMessage());
} finally {
ledgerRepository.save(batch);
}
}
}横切能力:一致性、性能与规则复杂度
数据一致性
挑战:员工主数据变更、考勤修正、绩效定稿等多源变更均影响薪酬口径,需降低 口径不一致 与 重复计算 风险。
思路:
- 以 领域事件 驱动跨模块通知,明确「谁产生事实、谁订阅消费」。
- 跨服务强一致场景结合 分布式事务或最终一致 + 对账(按团队基础设施选型)。
- 建立 定期对账与修正任务,将「可接受延迟」与「财务零差错」平衡写进运维手册。
性能与可扩展
挑战:考勤明细体量大,薪酬批算 CPU/IO 密集。
思路:
- Redis 缓存员工主数据、考勤规则等高频只读配置。
- 异步化:薪酬试算/定稿走队列,Worker 水平扩展。
- 数据库:索引与执行计划治理;大数据量表按时间与组织维度 分表/归档(按实际数据量级演进)。
示例:缓存考勤规则(Spring Cache 抽象,键要带组织/版本)
@Cacheable(cacheNames = "attendanceRules", key = "#orgId + ':' + #version")
public AttendanceRule getRule(Long orgId, String version) {
return ruleMapper.selectByOrgAndVersion(orgId, version);
}// 前端:员工详情页合并请求,减少碎片化接口(配合后端 BFF 更佳)
const [profile, contracts] = await Promise.all([
api.getEmployee(id),
api.getContracts(id),
]);复杂业务规则与工作流
挑战:制度频繁调整,硬编码难以维护。
思路:引入 规则引擎(如 Drools) 将可变的扣款、津贴、合规校验外置;审批流 可配置;通用能力沉淀为 业务中台服务,减少烟囱式重复开发。
权限模型(RBAC 精细化)
挑战:17 类角色 下同模块 按钮级差异大(导入导出、发布撤回、审批、个人/全员数据范围等)。
思路:
- 后端 接口级 + 数据范围 鉴权为唯一可信源。
- 前端
v-auth指令 +usePermissionHook统一消费权限元数据,避免各页面散落硬编码;角色权限在管理端 可配置,降低发版频率。
示例:v-auth 与 usePermission(Vue3)
// stores/permission.ts — 登录后拉平权限码(Pinia)
import { defineStore } from 'pinia';
import { api } from '@/api';
export const usePermissionStore = defineStore('permission', {
state: () => ({ codes: [] as string[] }),
actions: {
async load() {
const { data } = await api.getMyPermissions();
this.codes = data.codes ?? [];
},
can(code: string) {
return this.codes.includes(code);
},
},
});// composables/usePermission.ts
import { usePermissionStore } from '@/stores/permission';
export function usePermission() {
const store = usePermissionStore();
return { can: (code: string) => store.can(code) };
}// directives/auth.ts — 无权限则移除 DOM(也可改为 display:none + 无障碍说明)
import type { Directive } from 'vue';
import { usePermissionStore } from '@/stores/permission';
export const vAuth: Directive<HTMLElement, string> = {
mounted(el, binding) {
const store = usePermissionStore();
if (!store.can(binding.value)) el.parentNode?.removeChild(el);
},
};全局注册:app.directive('auth', vAuth),模板里写 v-auth。
<!-- 与后端 @PreAuthorize("hasAuthority('hr:payroll:export')") 等同权码 -->
<a-button v-auth="'hr:payroll:export'" type="primary" @click="onExport">
导出薪酬
</a-button>复盘小结
本项目复杂度集中在 排班与假勤的联动一致性、绩效薪酬的可配置计算、多角色细粒度权限 三块。通过 消息驱动的流程闭环、规则与 UI 编排外置、缓存与异步分摊峰值,在政务/大型组织场景下兼顾 合规、可运维与迭代效率。后续可补充:峰值 QPS/批算耗时、对账准确率、上线后缺陷密度 等量化指标,使复盘更具说服力。