xyc
4 天以前 cdccc9840978adb989f173b8d4763b7b5677f9b5
traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayBulletinService.java
@@ -1,6 +1,7 @@
package com.trafficaudit.holiday.service;
import com.trafficaudit.holiday.HolidayNumberUtils;
import com.trafficaudit.holiday.entity.HolidayCalendar;
import com.trafficaudit.holiday.service.HolidayStatService.DailyMetrics;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@@ -10,6 +11,7 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.annotation.Resource;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
@@ -43,6 +45,8 @@
    private String bulletinTemplatePath;
    private final HolidayStatService statService;
    @Resource
    private HolidayConfigService configService;
    private static final ThreadLocal<Document> CURRENT_DOCUMENT = new ThreadLocal<>();
    public HolidayBulletinService(HolidayStatService statService) {
@@ -56,9 +60,16 @@
        }
        DailyMetrics previousDay = current.getDayIndex() > 1
                ? statService.dailyMetrics(current.getYear(), current.getHolidayType(), current.getDayIndex() - 1) : null;
        HolidayCalendar previousDayConfig = configService.findPreviousDay(current.getYear(), current.getHolidayType());
        LocalDate previousDayDate = previousDayConfig == null || previousDayConfig.getHolidayDate() == null
                ? current.getDate().minusDays(1) : previousDayConfig.getHolidayDate();
        DailyMetrics previousCalendarDay = previousDay != null
                ? previousDay : statService.dailyMetricsByDate(previousDayDate);
        DailyMetrics previousYear = statService.dailyMetrics(current.getYear() - 1, current.getHolidayType(), current.getDayIndex());
        DailyMetrics twoYearsAgo = statService.dailyMetrics(current.getYear() - 2, current.getHolidayType(), current.getDayIndex());
        DailyMetrics currentCumulative = statService.cumulativeMetrics(current.getYear(), current.getHolidayType(), current.getDayIndex());
        DailyMetrics previousYearCumulative = statService.cumulativeMetrics(current.getYear() - 1, current.getHolidayType(), current.getDayIndex());
        DailyMetrics twoYearsAgoCumulative = statService.cumulativeMetrics(current.getYear() - 2, current.getHolidayType(), current.getDayIndex());
        if (current.getTotalPersonFlow() == null) {
            throw new IllegalArgumentException("所选日期的全社会跨区域人员流动量没有足够数据,无法生成快报");
@@ -69,14 +80,17 @@
                ? null : HolidayNumberUtils.divide(currentCumulative.getTotalPersonFlow(), BigDecimal.valueOf(10000)));
        String ringRatioClause = previousDay == null ? "" : ",环比" + ratioPhrase(
                current.getTotalPersonFlow(), previousDay.getTotalPersonFlow());
        String paragraph1 = String.format("%d月%d日(假期第%d天),全省全社会跨区域人员流动量%s万人次%s,比2025年同期%s。",
        String paragraph1 = String.format("%d月%d日(假期第%d天),全省全社会跨区域人员流动量%s万人次%s,比2025年同期%s,比2024年同期%s。",
                date.getMonthValue(), date.getDayOfMonth(), current.getDayIndex(), currentTotal,
                ringRatioClause,
                ratioPhrase(current.getTotalPersonFlow(), previousYear == null ? null : previousYear.getTotalPersonFlow()));
        String paragraph2 = String.format("假期以来,全省全社会跨区域人员流动量累计%s亿人次,比2025年同期%s。",
                ratioPhrase(current.getTotalPersonFlow(), previousYear == null ? null : previousYear.getTotalPersonFlow()),
                ratioPhrase(current.getTotalPersonFlow(), twoYearsAgo == null ? null : twoYearsAgo.getTotalPersonFlow()));
        String paragraph2 = String.format("假期以来,全省全社会跨区域人员流动量累计%s亿人次,比2025年同期%s,比2024年同期%s。",
                cumulativeTotalYi,
                ratioPhrase(currentCumulative.getTotalPersonFlow(),
                        previousYearCumulative == null ? null : previousYearCumulative.getTotalPersonFlow()));
                        previousYearCumulative == null ? null : previousYearCumulative.getTotalPersonFlow()),
                ratioPhrase(currentCumulative.getTotalPersonFlow(),
                        twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getTotalPersonFlow()));
        File template = resolveTemplateFile();
        if (!template.exists() || !template.isFile()) {
@@ -94,7 +108,8 @@
            try {
                replaceParagraph(document, text -> text.startsWith("10月") && text.contains("假期第"), paragraph1);
                replaceParagraph(document, text -> text.startsWith("假期以来"), paragraph2);
                fillTable(document, current, previousDay, previousYear, currentCumulative, previousYearCumulative);
                fillTable(document, current, previousDay, previousCalendarDay, previousYear, twoYearsAgo,
                        currentCumulative, previousYearCumulative, twoYearsAgoCumulative);
                byte[] replacedXml = serializeDocument(document);
                return replaceZipEntry(templateBytes, "word/document.xml", replacedXml);
            } finally {
@@ -106,8 +121,11 @@
    }
    private void fillTable(Document document, DailyMetrics current, DailyMetrics previousDay,
                           DailyMetrics previousYear, DailyMetrics currentCumulative,
                           DailyMetrics previousYearCumulative) {
                           DailyMetrics previousCalendarDay, DailyMetrics previousYear, DailyMetrics twoYearsAgo,
                           DailyMetrics currentCumulative, DailyMetrics previousYearCumulative,
                           DailyMetrics twoYearsAgoCumulative) {
        DailyMetrics firstDayRailBase = previousDay == null ? previousCalendarDay : previousDay;
        DailyMetrics firstDayCivilAviationBase = previousDay == null ? previousCalendarDay : previousDay;
        Element table = firstElement(document, "tbl");
        if (table == null) {
            throw new IllegalArgumentException("快报模板中找不到数据表");
@@ -116,54 +134,74 @@
                number(current.getNonBusinessPersonFlow()),
                ratio(current.getNonBusinessPersonFlow(), previousDay == null ? null : previousDay.getNonBusinessPersonFlow()),
                ratio(current.getNonBusinessPersonFlow(), previousYear == null ? null : previousYear.getNonBusinessPersonFlow()),
                "—",
                ratio(current.getNonBusinessPersonFlow(), twoYearsAgo == null ? null : twoYearsAgo.getNonBusinessPersonFlow()),
                number(currentCumulative.getNonBusinessPersonFlow()),
                ratio(currentCumulative.getNonBusinessPersonFlow(),
                        previousYearCumulative == null ? null : previousYearCumulative.getNonBusinessPersonFlow()),
                "—"
                ratio(currentCumulative.getNonBusinessPersonFlow(),
                        twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getNonBusinessPersonFlow())
        });
        writeTableRow(table, 3, new String[]{
                number(current.getRoad()),
                ratio(current.getRoad(), previousDay == null ? null : previousDay.getRoad()),
                ratio(current.getRoad(), previousYear == null ? null : previousYear.getRoad()),
                "—",
                ratio(current.getRoad(), twoYearsAgo == null ? null : twoYearsAgo.getRoad()),
                number(currentCumulative.getRoad()),
                ratio(currentCumulative.getRoad(), previousYearCumulative == null ? null : previousYearCumulative.getRoad()),
                "—"
                ratio(currentCumulative.getRoad(), twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getRoad())
        });
        writeTableRow(table, 4, new String[]{
                number(current.getRoadPersonFlow()),
                ratio(current.getRoadPersonFlow(), previousDay == null ? null : previousDay.getRoadPersonFlow()),
                ratio(current.getRoadPersonFlow(), previousYear == null ? null : previousYear.getRoadPersonFlow()),
                "—",
                ratio(current.getRoadPersonFlow(), twoYearsAgo == null ? null : twoYearsAgo.getRoadPersonFlow()),
                number(currentCumulative.getRoadPersonFlow()),
                ratio(currentCumulative.getRoadPersonFlow(), previousYearCumulative == null ? null : previousYearCumulative.getRoadPersonFlow()),
                "—"
                ratio(currentCumulative.getRoadPersonFlow(),
                        previousYearCumulative == null ? null : previousYearCumulative.getRoadPersonFlow()),
                ratio(currentCumulative.getRoadPersonFlow(),
                        twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getRoadPersonFlow())
        });
        writeTableRow(table, 5, transportRow(current.getRail(), previousDay == null ? null : previousDay.getRail(),
                previousYear == null ? null : previousYear.getRail(), currentCumulative.getRail(),
                previousYearCumulative == null ? null : previousYearCumulative.getRail()));
        writeTableRow(table, 6, transportRow(current.getCivilAviation(), previousDay == null ? null : previousDay.getCivilAviation(),
                previousYear == null ? null : previousYear.getCivilAviation(), currentCumulative.getCivilAviation(),
                previousYearCumulative == null ? null : previousYearCumulative.getCivilAviation()));
        writeTableRow(table, 7, transportRow(current.getWater(), previousDay == null ? null : previousDay.getWater(),
                previousYear == null ? null : previousYear.getWater(), currentCumulative.getWater(),
                previousYearCumulative == null ? null : previousYearCumulative.getWater()));
        writeTableRow(table, 8, transportRow(current.getTotalPersonFlow(), previousDay == null ? null : previousDay.getTotalPersonFlow(),
                previousYear == null ? null : previousYear.getTotalPersonFlow(), currentCumulative.getTotalPersonFlow(),
                previousYearCumulative == null ? null : previousYearCumulative.getTotalPersonFlow()));
        writeTableRow(table, 5, transportRow(current.getRail(),
                firstDayRailBase == null ? null : firstDayRailBase.getRail(),
                previousYear == null ? null : previousYear.getRail(),
                twoYearsAgo == null ? null : twoYearsAgo.getRail(),
                currentCumulative.getRail(),
                previousYearCumulative == null ? null : previousYearCumulative.getRail(),
                twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getRail()));
        writeTableRow(table, 6, transportRow(current.getCivilAviation(),
                firstDayCivilAviationBase == null ? null : firstDayCivilAviationBase.getCivilAviation(),
                previousYear == null ? null : previousYear.getCivilAviation(),
                twoYearsAgo == null ? null : twoYearsAgo.getCivilAviation(),
                currentCumulative.getCivilAviation(),
                previousYearCumulative == null ? null : previousYearCumulative.getCivilAviation(),
                twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getCivilAviation()));
        writeTableRow(table, 7, transportRow(current.getWater(),
                previousDay == null ? null : previousDay.getWater(),
                previousYear == null ? null : previousYear.getWater(),
                twoYearsAgo == null ? null : twoYearsAgo.getWater(),
                currentCumulative.getWater(),
                previousYearCumulative == null ? null : previousYearCumulative.getWater(),
                twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getWater()));
        writeTableRow(table, 8, transportRow(current.getTotalPersonFlow(),
                previousDay == null ? null : previousDay.getTotalPersonFlow(),
                previousYear == null ? null : previousYear.getTotalPersonFlow(),
                twoYearsAgo == null ? null : twoYearsAgo.getTotalPersonFlow(),
                currentCumulative.getTotalPersonFlow(),
                previousYearCumulative == null ? null : previousYearCumulative.getTotalPersonFlow(),
                twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getTotalPersonFlow()));
    }
    private String[] transportRow(BigDecimal current, BigDecimal previousDay, BigDecimal previousYear,
                                  BigDecimal currentCumulative, BigDecimal previousYearCumulative) {
                                  BigDecimal twoYearsAgo, BigDecimal currentCumulative,
                                  BigDecimal previousYearCumulative, BigDecimal twoYearsAgoCumulative) {
        return new String[]{
                number(current),
                ratio(current, previousDay),
                ratio(current, previousYear),
                "—",
                ratio(current, twoYearsAgo),
                number(currentCumulative),
                ratio(currentCumulative, previousYearCumulative),
                "—"
                ratio(currentCumulative, twoYearsAgoCumulative)
        };
    }
@@ -175,7 +213,7 @@
        int logicalColumn = 0;
        for (Element cell : cells) {
            int span = gridSpan(cell);
            if (logicalColumn >= 2 && logicalColumn < 9) {
            if (logicalColumn >= 2) {
                int valueIndex = logicalColumn - 2;
                if (valueIndex < values.length) {
                    setCellText(cell, values[valueIndex]);