跳到主要内容

节假日

节假日子域提供中国法定节假日 / 工作日的数据同步与本地查询能力。它有两个面向:一端对接外部数据源 api.apihubs.cn(拉取与代理),另一端把数据落成本地 Holiday / EnumGroup 表,供业务稳定、可离线地查询。

节假日同步是手动触发的(启动时自动同步的宿主服务 SampleHostedService 目前已被注释掉)。首次使用必须先触发一次同步把数据灌入本地库,本地查询才有数据。

业务能力

  • 远端代理查询:直接转发 api.apihubs.cnholiday/getenum/get,透传原始响应。适合需要实时、未被本地覆盖的查询。
  • 本地同步:把指定年份区间的节假日数据落库,并同步枚举基础数据(如「工作日 / 周末 / 法定假日」等 EnumGroup)。
  • 本地查询:从数据库按日期 / 年份 / 月份 / 是否工作日等条件分页查询,并支持下拉用枚举列表。这是业务代码最常走的路径。
  • CRUD:节假日记录的新增 / 更新 / 删除(受 plat.Holiday 权限保护)。

:::caution 当前授权边界 HolidayController 直接继承 ControllerBase。当前只有新增、更新、删除显式标注 [Authorize("plat.Holiday")];远端代理、同步和本地查询 Action 没有显式授权特性。若这些端点不应公开,需要在代码或网关层补齐策略,不能仅凭文档假设它们已受保护。 :::

date 参数格式为 yyyyMMdd(如 20250101 = 2025-01-01)。HolidayQuery 支持 year / month / date / workday / weekend / holiday_legal / holiday_recess / lunar / cn 等过滤条件,这些枚举分组都来自 api.apihubs.cnenum/get

概念与关系

两个服务职责清晰分离:

  • IHolidayService:本地数据的读写与查询。GetHolidayByDateAsync(int date) / GetHolidayList(HolidayQuery) / GetEnumList(string enum) 等。
  • IHolidayManager:与外部 API 对接的同步逻辑。SyncHolidayAsync(beginYear, endYear) 按年份区间拉取并落库;SyncEnum() 同步枚举基础数据。它实现 IDomainService,是「外部数据源 → 本地表」的桥。

为什么需要本地同步与缓存

节假日数据变化极低频(一年调一两次),但查询极高频(判断“今天是否工作日”之类的调用可能每天发生无数次)。如果不落地,每次查询都打 api.apihubs.cn 会带来几个问题:

  1. 外部依赖与限流:远端接口带 api_key 并有调用限制,高频透传既不经济也不稳定。
  2. 可离线、可组合:本地表能按 workday/holiday_legal 等条件做任意组合过滤和分页,而代理接口做不到。
  3. 审计与修正:业务可能需要对个别日期人工 CRUD 覆盖(如特殊调休),只有落库后这些修正才有存放之处。

因此设计成"低频同步 + 高频本地查":同步是手动/低频动作,查询走本地 FreeSql,外部 API 只在代理与同步两种场景出现。

配置(HolidayAppOption

绑定自配置节 HolidayAppOption,决定同步覆盖的年份区间与远端凭据:

业务含义
BeginYear同步起始年份
EndYear同步结束年份
ApiKeyapi.apihubs.cn 的密钥(代理 /hubs/* 与同步时按需透传)
{
"HolidayAppOption": {
"BeginYear": 2024,
"EndYear": 2026,
"ApiKey": "your-apihubs-key"
}
}

开发示例

// 注入应用服务做本地查询
private readonly IHolidayService _holidayService;

// 查某天是否为工作日
var day = await _holidayService.GetHolidayByDateAsync(20250101);
bool isWorkday = day?.workday == 1;

// 按条件分页拉取
var list = await _holidayService.GetHolidayList(new HolidayQuery { year = "2025", size = 31 });
// 手动触发一次同步(年份区间来自 HolidayAppOption)
private readonly IHolidayManager _holidayManager;

await _holidayManager.SyncHolidayAsync(2024, 2026);
await _holidayManager.SyncEnum();

相关文档