feat(holiday): expose 2019 holiday configuration
| | |
| | | - **正常导入口径**:只读取所选年份的当年列(2026 年铁路/民航/道路/水路为 C 列、高速为 C 列、普通国省道为 D 列);同时只额外读取当前年份铁路/民航的“前一日”行。2019/2024/2025 历史列不参与导入。 |
| | | - **快报口径**:同比只使用 2025、2024;假期第 1 日的铁路、民航环比使用“前一日”数据,公路、水路、总计及其他口径第 1 日仍显示“—”;第 2 日起正常计算环比。 |
| | | - **迁移脚本**:`docs/sql_holiday_previous_day_migration.sql`,部署包同步为 `deploy-templates/db/sql_holiday_previous_day_migration.sql`,脚本可重复执行。 |
| | | - **2019 显示补齐(10-03 晚追加)**:`holiday_calendar` 增加 2019-10-01 至 2019-10-08 配置;系统配置-节假日管理和专项统计-节假日均增加 2019 年份,历史库执行幂等迁移后即可查看 2019 年 8 天道路数据。 |
| | | - **验证(本机 3305 库 + 真实模板)**:接口导入结果 `passengerRows=10, vehicleRows=4, successRows=14, failRows=0`;数据库抽查 2026-09-30 铁路=82.1、民航=6.6994,2026-10-01 铁路=113.8、民航=6.7482、道路=78.82、水路=1.311,2026-10-02 铁路=82.0、民航=6.3914、道路=75.61、水路=3.3373;2026-10-01 快报铁路环比=+38.6%、民航环比=+0.7%,总行环比为“—”;2026-10-02 铁路环比=-27.9%、民航环比=-5.3%。 |
| | | - **运行状态**:后端 8090(重启后已加载新代码)、前端 8080 均在运行;访问 `http://localhost:8080`。 |
| | | |
| | |
| | | -- Add the previous-day row used by rail and civil-aviation ring-ratio calculations. |
| | | -- day_index = 0 identifies the configured previous day; normal holiday days remain 1..N. |
| | | -- Backfill the 2019 National Day calendar and previous-day rows used by rail and civil-aviation ring-ratio calculations. |
| | | -- day_index = 0 identifies the configured previous day; 2019 uses normal days 1..8. |
| | | INSERT IGNORE INTO holiday_calendar |
| | | (year, holiday_type, holiday_date, day_index, created_at, updated_at) |
| | | VALUES |
| | | (2019, 'NATIONAL_DAY', '2019-10-01', 1, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-02', 2, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-03', 3, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-04', 4, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-05', 5, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-06', 6, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-07', 7, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-08', 8, NOW(), NOW()), |
| | | (2024, 'NATIONAL_DAY', '2024-09-30', 0, NOW(), NOW()), |
| | | (2025, 'NATIONAL_DAY', '2025-09-30', 0, NOW(), NOW()), |
| | | (2026, 'NATIONAL_DAY', '2026-09-30', 0, NOW(), NOW()); |
| | |
| | | - 公路人员流动量 = 道路营业性客运量 + 非营业性人员流动量。 |
| | | - 总人员流动量 = 公路 + 铁路 + 民航 + 水路。 |
| | | - 导入按“年份 + 节假日分类”读取 `holiday_calendar` 中 `day_index>=1` 的日期,将工作簿“第N日”行覆盖写入当年客流/车流;同时读取当前年份铁路、民航的“前一日”行,写入 `day_index=0` 对应的日期。 |
| | | - 日常导入只读取所选年份的当年列(道路表的 2019/2024/2025 列均不读取);2019 年道路数据和 2024/2025/2026 年前一日铁路、民航数据由启动初始化直接写入数据库。 |
| | | - 日常导入只读取所选年份的当年列(道路表的 2019/2024/2025 列均不读取);2019 年道路数据和 2024/2025/2026 年前一日铁路、民航数据由启动初始化直接写入数据库。2019 年 10 月 1-8 日的 `holiday_calendar` 配置用于在系统配置和节假日统计页查看该历史基线。 |
| | | - 导入前检查比本次最新导入日更早的历史日期是否发生变化;如有变化先不写库,返回差异清单,用户确认后才允许覆盖。 |
| | | - 记录“前一日”的铁路、民航数据后,假期第 1 日的铁路、民航环比按该数据计算;公路、水路、总人员流动量在第 1 日仍不计算环比。 |
| | | - 导出以源工作簿为底稿,回填库内数据与客运系数;快报按日期生成 Word,同比固定使用 2025、2024 两年,不使用 2019 数据。 |
| | |
| | | -- Add the previous-day row used by rail and civil-aviation ring-ratio calculations. |
| | | -- day_index = 0 identifies the configured previous day; normal holiday days remain 1..N. |
| | | -- Backfill the 2019 National Day calendar and previous-day rows used by rail and civil-aviation ring-ratio calculations. |
| | | -- day_index = 0 identifies the configured previous day; 2019 uses normal days 1..8. |
| | | INSERT IGNORE INTO holiday_calendar |
| | | (year, holiday_type, holiday_date, day_index, created_at, updated_at) |
| | | VALUES |
| | | (2019, 'NATIONAL_DAY', '2019-10-01', 1, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-02', 2, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-03', 3, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-04', 4, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-05', 5, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-06', 6, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-07', 7, NOW(), NOW()), |
| | | (2019, 'NATIONAL_DAY', '2019-10-08', 8, NOW(), NOW()), |
| | | (2024, 'NATIONAL_DAY', '2024-09-30', 0, NOW(), NOW()), |
| | | (2025, 'NATIONAL_DAY', '2025-09-30', 0, NOW(), NOW()), |
| | | (2026, 'NATIONAL_DAY', '2026-09-30', 0, NOW(), NOW()); |
| | |
| | | options.put("transportModes", TRANSPORT_MODE_LABELS); |
| | | options.put("roadCategories", ROAD_CATEGORY_LABELS); |
| | | options.put("vehicleTypes", VEHICLE_TYPE_LABELS); |
| | | options.put("years", Arrays.asList(2024, 2025, 2026)); |
| | | options.put("years", Arrays.asList(2019, 2024, 2025, 2026, 2027, 2028, 2029, 2030)); |
| | | return options; |
| | | } |
| | | } |
| | |
| | | if (!configService.listHolidays(null, null).isEmpty()) { |
| | | return; |
| | | } |
| | | int[] lengths = {7, 8, 8}; |
| | | for (int i = 0; i < REFERENCE_YEARS.length; i++) { |
| | | int year = REFERENCE_YEARS[i]; |
| | | int[] calendarYears = {2019, 2024, 2025, 2026}; |
| | | int[] lengths = {8, 7, 8, 8}; |
| | | for (int i = 0; i < calendarYears.length; i++) { |
| | | int year = calendarYears[i]; |
| | | List<HolidayCalendar> existing = configService.findHolidayDays(year, HolidayConstants.TYPE_NATIONAL_DAY); |
| | | Map<Integer, HolidayCalendar> byDay = new LinkedHashMap<>(); |
| | | for (HolidayCalendar row : existing) { |
| | |
| | | calendar.setUpdatedAt(LocalDateTime.now()); |
| | | configService.saveHoliday(toMap(calendar)); |
| | | } |
| | | if (year == 2019) { |
| | | continue; |
| | | } |
| | | HolidayCalendar previousDay = new HolidayCalendar(); |
| | | previousDay.setYear(year); |
| | | previousDay.setHolidayType(HolidayConstants.TYPE_NATIONAL_DAY); |
| | |
| | | name: 'HolidayStat', |
| | | data() { |
| | | return { |
| | | years: [2024, 2025, 2026, 2027, 2028, 2029, 2030], |
| | | years: [2019, 2024, 2025, 2026, 2027, 2028, 2029, 2030], |
| | | year: 2026, |
| | | holidayType: 'NATIONAL_DAY', |
| | | holidayTypeOptions: [], |
| | |
| | | data() { |
| | | return { |
| | | activeTab: 'holidays', |
| | | years: [2024, 2025, 2026, 2027, 2028, 2029, 2030], |
| | | years: [2019, 2024, 2025, 2026, 2027, 2028, 2029, 2030], |
| | | holidayTypeOptions: [], |
| | | dateCategoryOptions: [], |
| | | holidayQuery: { year: 2026, holidayType: 'NATIONAL_DAY' }, |