你知道节假日是如何设计的嘛?SpringBoot+Vue3 休假、补班、部门考勤关联如何不写死在代码里
🌐 演示地址:ruoyioffice.com | 📦 源码1:ruoyi-office-vben | 📦 源码2:ruoyi-office | 📦 源码3:ruoyi-office
RuoYi Office · 一个平台,管好整个企业
每到节假日前后,HR 最容易被问到的问题不是“能不能请假”,而是“这一天到底算不算工作日”。如果系统只用周一到周五判断工作日,遇到调休补班就会立刻出错。RuoYi Office 的做法是把节假日设计成“年度方案 + 日期明细 + 部门考勤关联”,让法定假期、企业自定义假期、周末补班都可以通过配置生效。
▲ 节假日方案配置链路:年度方案维护休假/补班明细,部门考勤配置选择方案,工作日判断时节假日明细优先于周规则
引言:为什么节假日不能写死?
很多考勤系统一开始都会写一个简单判断:
boolean isWorkDay = dayOfWeek >= 1 && dayOfWeek <= 5;
这个逻辑在普通周内没问题,但一到节假日就会失效。
| 场景 | 只按星期判断的结果 | 正确结果 |
|---|---|---|
| 工作日遇到法定休假 | 继续生成缺卡 | 不需要打卡 |
| 周末遇到调休补班 | 不生成考勤记录 | 应按工作日处理 |
| 公司年会假、厂休日 | 系统无法识别 | HR 可配置休假 |
| 分公司地区性假期 | 全公司规则一致 | 部门可绑定不同方案 |
真正可落地的企业系统,应该把“节假日”从代码里拿出来,变成 HR 可维护的数据。
一、业务设计:节假日其实有两种相反含义
节假日配置看起来是“放假日期列表”,但在考勤里至少有两类明细。
| 明细类型 | 业务含义 | 示例 |
|---|---|---|
| 休假 | 原本可能是工作日,但当天不用上班 | 5 月 1 日劳动节 |
| 补班 | 原本可能是周末,但当天需要上班 | 某个周日调休补班 |
这就是为什么 RuoYi Office 的节假日明细里保留 type 字段,而不是只存一个日期数组。休假 和 补班 对最终工作日判断的影响完全相反。
1.1 三层配置模型
RuoYi Office 将节假日能力拆成三层:
| 层级 | 前端入口 | 后端对象 | 作用 |
|---|---|---|---|
| 年度方案 | 节假日方案管理弹窗 | HolidayPlanDO | 定义某一年度、某一套假期方案 |
| 日期明细 | 方案明细表格 | HolidayPlanDetailDO | 维护休假/补班日期 |
| 考勤关联 | 考勤规则配置页 | AttendanceConfigDO.holidayPlanId | 指定部门使用哪套方案 |
这样设计后,系统可以同时维护多套方案,例如“2026 年国家法定节假日”“集团总部 2026 假期安排”“制造基地春节厂休方案”。
1.2 节假日明细必须优先于周规则
最终判断顺序应该是:
| 优先级 | 判断来源 | 结果 |
|---|---|---|
| 1 | 日期命中节假日明细,类型为休假 | 非工作日 |
| 2 | 日期命中节假日明细,类型为补班 | 工作日 |
| 3 | 未命中特殊日期 | 回落到部门工作日设置 |
这个优先级非常关键。没有它,调休补班和法定休假都会被周规则覆盖。
二、前端设计:HR 维护的是“方案”,不是代码
考勤配置页面把“工作日设置”和“应用节假日方案”放在同一张表单里。HR 先选择部门,再配置该部门的工作日、上下班时间、打卡模式和节假日方案。
<Form.Item label="应用节假日方案">
<div class="flex items-center gap-2">
<Select
v-model:value="formData.holidayPlanId"
:options="holidayPlanOptions"
placeholder="请选择要应用的节假日方案"
allow-clear
class="w-80"
/>
<Button @click="holidayPlanModalOpen = true">配置</Button>
</div>
</Form.Item>

▲ HRM / 考勤管理 / 考勤配置 页面,截取“工作日设置 + 应用节假日方案”区域
节假日方案弹窗支持列表和表单两种视图:列表看有哪些年度方案,表单维护年度、状态、备注和日期明细。
const newDetail = ref({
holidayDate: '',
name: '',
type: 1,
});
function handleAddDetail() {
const exists = formData.value.details?.some(
(d) => d.holidayDate === newDetail.value.holidayDate,
);
if (exists) {
message.warning('该日期已存在');
return;
}
formData.value.details = [...(formData.value.details || []), newDetail.value];
formData.value.details.sort((a, b) =>
(a.holidayDate || '').localeCompare(b.holidayDate || ''),
);
}
这段前端逻辑有两个细节:

| 细节 | 价值 |
|---|---|
| 同一日期不允许重复添加 | 避免一天同时被配置成休假和补班 |
| 添加后按日期排序 | 方便 HR 检查年度安排是否遗漏 |
三、后端设计:主表负责方案,明细负责覆盖
节假日方案不适合放到字典里,因为它是有年度、有明细、有状态的业务配置。更合理的模型是主从表。
| 表 | 核心字段 | 说明 |
|---|---|---|
hrm_holiday_plan | name、year、status、remark | 方案主表 |
hrm_holiday_plan_detail | plan_id、holiday_date、type、name | 方案日期明细 |
hrm_attendance_config | dept_id、work_days、holiday_plan_id | 部门考勤配置 |
保存方案时,后端通常采用“先保存主表,再重建明细”的方式,确保前端传来的最新明细就是数据库最终状态。
@Transactional(rollbackFor = Exception.class)
public Long saveHolidayPlan(HolidayPlanSaveReqVO reqVO) {
HolidayPlanDO plan = BeanUtils.toBean(reqVO, HolidayPlanDO.class);
if (plan.getId() == null) {
holidayPlanMapper.insert(plan);
} else {
holidayPlanMapper.updateById(plan);
holidayPlanDetailMapper.deleteByPlanId(plan.getId());
}
for (HolidayPlanSaveReqVO.Detail detail : reqVO.getDetails()) {
HolidayPlanDetailDO detailDO = BeanUtils.toBean(detail, HolidayPlanDetailDO.class);
detailDO.setPlanId(plan.getId());
holidayPlanDetailMapper.insert(detailDO);
}
return plan.getId();
}
这类配置的核心不是 CRUD,而是把配置结果稳定地接入工作日判断链路。
四、工作日判断:配置最终要落到业务结果
节假日方案的价值,最终体现在“今天是否需要打卡”“是否生成考勤记录”“统计是否算缺勤”。
public boolean isWorkDay(AttendanceConfigDO config, LocalDate date) {
HolidayPlanDetailDO detail = holidayPlanDetailMapper
.selectByPlanIdAndDate(config.getHolidayPlanId(), date);
if (detail != null) {
return Integer.valueOf(2).equals(detail.getType()); // 2=补班
}
int weekValue = date.getDayOfWeek().getValue();
return StrUtil.split(config.getWorkDays(), ',')
.stream()
.map(Integer::valueOf)
.anyMatch(item -> item == weekValue);
}
这个判断链路遵循一个原则:特殊日期优先,常规星期兜底。
| 日期 | 周规则 | 节假日明细 | 最终结果 |
|---|---|---|---|
| 普通周三 | 工作日 | 无 | 工作日 |
| 劳动节周五 | 工作日 | 休假 | 非工作日 |
| 调休周日 | 休息日 | 补班 | 工作日 |
五、企业落地建议
节假日方案看似简单,实际落地时建议把职责边界设计清楚。
| 角色 | 负责内容 |
|---|---|
| HR 管理员 | 每年维护法定节假日方案,确认调休补班 |
| 部门负责人 | 确认本部门是否使用默认方案,是否有特殊厂休 |
| 系统管理员 | 控制配置权限,避免普通员工误改方案 |
| 考勤统计人员 | 在月度统计前检查方案是否完整 |
推荐操作流程:
- 年初创建当年节假日方案。
- 录入所有法定休假日期。
- 录入调休补班日期。
- 在部门考勤配置中选择该方案。
- 月度统计前抽查特殊日期的考勤结果。
六、技术亮点总结
| 设计点 | 实现方式 | 价值 |
|---|---|---|
| 节假日配置化 | 主表 + 明细表 | 不需要改代码适配每年放假安排 |
| 休假/补班双类型 | type=1/2 | 同时处理工作日放假与周末补班 |
| 部门关联 | holidayPlanId | 不同组织可使用不同假期方案 |
| 明细优先 | 日期命中后覆盖周规则 | 避免法定假期被星期规则误判 |
| 前端弹窗维护 | 列表视图 + 表单视图 | HR 可独立维护年度方案 |
结语
节假日方案不是一个日期工具函数,而是企业假勤系统的基础配置能力。只有把“法定休假、调休补班、企业自定义假期、部门差异化”都纳入配置模型,后面的打卡、请假、统计和薪资计算才有稳定基础。
💡 RuoYi Office —— 一个平台,管好整个企业
🌐 在线演示:ruoyioffice.com/web/(账号 admin / admin123)
💬 技术咨询:添加 17156169080,备注「RuoYi Office」
⭐ 如果觉得不错,请给个 Star 支持一下!

