你知道节假日是如何设计的嘛?SpringBoot+Vue3 休假、补班、部门考勤关联如何不写死在代码里

0 阅读6分钟

你知道节假日是如何设计的嘛?SpringBoot+Vue3 休假、补班、部门考勤关联如何不写死在代码里

🌐 演示地址ruoyioffice.com | 📦 源码1ruoyi-office-vben | 📦 源码2ruoyi-office | 📦 源码3ruoyi-office

RuoYi Office · 一个平台,管好整个企业 image.png

每到节假日前后,HR 最容易被问到的问题不是“能不能请假”,而是“这一天到底算不算工作日”。如果系统只用周一到周五判断工作日,遇到调休补班就会立刻出错。RuoYi Office 的做法是把节假日设计成“年度方案 + 日期明细 + 部门考勤关联”,让法定假期、企业自定义假期、周末补班都可以通过配置生效。 hrm-holiday-plan-config-flow.png

▲ 节假日方案配置链路:年度方案维护休假/补班明细,部门考勤配置选择方案,工作日判断时节假日明细优先于周规则

引言:为什么节假日不能写死?

很多考勤系统一开始都会写一个简单判断:

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>

image.png

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 || ''),
  );
}

这段前端逻辑有两个细节: image.png

细节价值
同一日期不允许重复添加避免一天同时被配置成休假和补班
添加后按日期排序方便 HR 检查年度安排是否遗漏

三、后端设计:主表负责方案,明细负责覆盖

节假日方案不适合放到字典里,因为它是有年度、有明细、有状态的业务配置。更合理的模型是主从表。

核心字段说明
hrm_holiday_plannameyearstatusremark方案主表
hrm_holiday_plan_detailplan_idholiday_datetypename方案日期明细
hrm_attendance_configdept_idwork_daysholiday_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 管理员每年维护法定节假日方案,确认调休补班
部门负责人确认本部门是否使用默认方案,是否有特殊厂休
系统管理员控制配置权限,避免普通员工误改方案
考勤统计人员在月度统计前检查方案是否完整

推荐操作流程:

  1. 年初创建当年节假日方案。
  2. 录入所有法定休假日期。
  3. 录入调休补班日期。
  4. 在部门考勤配置中选择该方案。
  5. 月度统计前抽查特殊日期的考勤结果。

六、技术亮点总结

设计点实现方式价值
节假日配置化主表 + 明细表不需要改代码适配每年放假安排
休假/补班双类型type=1/2同时处理工作日放假与周末补班
部门关联holidayPlanId不同组织可使用不同假期方案
明细优先日期命中后覆盖周规则避免法定假期被星期规则误判
前端弹窗维护列表视图 + 表单视图HR 可独立维护年度方案

结语

节假日方案不是一个日期工具函数,而是企业假勤系统的基础配置能力。只有把“法定休假、调休补班、企业自定义假期、部门差异化”都纳入配置模型,后面的打卡、请假、统计和薪资计算才有稳定基础。

💡 RuoYi Office —— 一个平台,管好整个企业

🌐 在线演示ruoyioffice.com/web/(账号 admin / admin123)

💬 技术咨询:添加 17156169080,备注「RuoYi Office」

如果觉得不错,请给个 Star 支持一下!