From 54e10aee11aa4a10926df02782ca07d41eeb9b98 Mon Sep 17 00:00:00 2001
From: xyc <jc_xiong@hotmail.com>
Date: 星期二, 06 十月 2026 16:19:07 +0800
Subject: [PATCH] fix(holiday): 加大折线图纵向间距并同步 Word 尺寸

---
 HANDOFF.md                                                                                            |   17 ++++++++
 traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendChartService.java     |   16 ++++++-
 traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendService.java          |   29 ++++++++------
 traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendChartServiceTest.java |   16 ++++++++
 4 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/HANDOFF.md b/HANDOFF.md
index 84e7f3b..aa3a518 100644
--- a/HANDOFF.md
+++ b/HANDOFF.md
@@ -6,6 +6,23 @@
 
 ## 鏈�鏂帮紙2026-10-06锛�
 
+### 10-06锛氭姌绾垮浘绾靛悜闂磋窛鍔犻珮锛堥獙鏀堕�氳繃锛�
+
+- **鐢ㄦ埛鑳屾櫙**锛氬杩愰噺鍥剧嚎闂磋窛杈冨ソ銆佹爣绛炬憜鏀惧悎鐞嗭紱鍏朵粬澶氬簭鍒楁姌绾垮浘鍥犵嚎璺濆亸杩戯紝鏍囩浠嶅彲鑳藉帇绾裤�傜敤鎴峰悓鎰忛�傚綋澧炲姞鍥鹃珮锛學ord 鍙槸鍙栧浘鏉ユ簮锛屼笉瑕佹眰褰撳墠鍒嗛〉涓烘渶缁堢増锛屼絾鍥句笉鑳借繃楂樸��
+- **瀹炵幇**锛�
+  - `HolidayTrendChartService`锛氭姌绾跨旱杞寸暀鐧芥敹绱т负 `lowerMargin=0.04 / upperMargin=0.07`锛沗LINE_CHART_HEIGHT_SCALE=1.20`锛屾墍鏈夋姌绾� PNG 楂樺害鏀惧ぇ绾� 20%銆�
+  - `HolidayTrendService`锛�12 寮犳姌绾垮浘鐨� Word 鍐呭祵鍥剧墖楂樺害鍚屾鏀惧ぇ绾� 20%锛屼繚鎸� PNG 涓� Word 鍥剧墖妗嗘瘮渚嬩竴鑷达紱楗煎浘銆佸爢鍙犲浘鏈敼銆�
+  - `HolidayTrendChartServiceTest`锛氭柊澧炴姌绾垮浘楂樺害缂╂斁鏂█銆�
+- **楠屾敹**锛氱敤鎴蜂簬 2026-10-06 鏌ョ湅 `C:\Users\jcxiong\Downloads\2026骞村崄涓�鍋囨湡鍏ㄧ渷缁煎悎杩愯緭瀹㈡祦閲忚蛋鍔垮浘锛堟姌绾垮姞楂�20瀹為獙锛�.docx` 鍚庨獙鏀堕�氳繃銆�
+- **楠岃瘉缁撴灉**锛�
+  1. 15% 鍔犻珮鐗堝湪閾佽矾瀹㈣繍閲忓浘 `image5` 妫�鍑� OCR 鏍囩妗嗛噸鍙狅紱20% 鐗� 12 寮犳姌绾垮浘锛坄image1/2/4/5/6/7/8/9/10/11/14/15`锛夋湭妫�鍑烘爣绛炬閲嶅彔銆�
+  2. PNG 瀹介珮姣斾笌 Word `wp:extent` 瀹介珮姣旀渶澶ц宸害 `0.162%`锛屾湭鍙戠敓鏄庢樉鎷変几銆�
+  3. Word 浠嶄负 8 椤点�佹瘡椤� 2 寮犲浘锛堥椤� 1 寮狅級锛屼笌 15% 鍔犻珮瀹為獙鐩稿悓銆�
+  4. 鍚庣鍏ㄩ噺 `mvn -q test -f traffic-audit-server\pom.xml` 閫氳繃锛沗HolidayTrendChartServiceTest` 鑱氱劍娴嬭瘯閫氳繃銆�
+  5. 鏍囩浜插拰搴︽鏌ヨ褰曞埌 3 澶勬爣绛炬鏇撮潬杩戦偦杩戠嚎锛坄image1` 鐨� `1,518.02`銆乣image4` 鐨� `1,346.17`銆乣image9` 鐨� `248.65`锛夛紱鐧芥弿杈逛繚璇佸彲璇伙紝鐢ㄦ埛鏁翠綋楠屾敹閫氳繃骞朵繚鐣欒鎺掔増绛栫暐銆�
+  6. `image13` 鍫嗗彔鍥炬湁 4 澶� OCR 鏍囩閲嶅彔锛屼絾璇ュ浘鏈弬涓庢湰瀹為獙涓斾唬鐮佹湭鏀广��
+- **鏁版嵁杈圭晫**锛氭湭瀵煎叆銆佽鐩栨垨閲嶅浠讳綍涓氬姟鏁版嵁锛涗粎鏈湴鍙鐢熸垚璧板娍鍥惧仛瀹為獙銆�
+
 ### 10-06锛氬钩鍧囨嫢鎸ゅ害鏍囩鎭㈠涓� 2 浣嶅皬鏁�
 
 - **璋冩暣**锛氭寜鐢ㄦ埛瑕佹眰锛屸�滄櫘閫氬浗鐪侀亾瑙傛祴绔欏钩鍧囨嫢鎸ゅ害鈥濅笉鍐嶅崟鐙娇鐢� 3 浣嶅皬鏁帮紝鎭㈠涓烘姌绾垮浘榛樿 2 浣嶃��
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendChartService.java b/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendChartService.java
index d01765e..47bd7ca 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendChartService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendChartService.java
@@ -78,6 +78,7 @@
     private static final double ITEM_LABEL_GAP = 10.0;
     private static final float HALO_OUTLINE_WIDTH = 4.0f;
     private static final int PERCENT_ITEM_LABEL_DECIMALS = 1;
+    private static final double LINE_CHART_HEIGHT_SCALE = 1.20;
     private static final Color ITEM_LABEL_COLOR = new Color(55, 55, 55);
     private static final Color[] SERIES_COLORS = {
             new Color(192, 80, 77),
@@ -141,8 +142,8 @@
 
         NumberAxis rangeAxis = new NumberAxis();
         rangeAxis.setAutoRangeIncludesZero(false);
-        rangeAxis.setLowerMargin(0.12);
-        rangeAxis.setUpperMargin(0.16);
+        rangeAxis.setLowerMargin(0.04);
+        rangeAxis.setUpperMargin(0.07);
         rangeAxis.setTickLabelFont(TICK_FONT);
         rangeAxis.setLabelFont(LABEL_FONT);
         rangeAxis.setTickLabelPaint(MUTED_TEXT_COLOR);
@@ -173,7 +174,8 @@
                     BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
         }
         plot.setRenderer(renderer);
-        return render(chart, width, height, yAxisLabel, true, percentAxis, valueDecimals);
+        return render(chart, width, scaleLineChartHeight(height),
+                yAxisLabel, true, percentAxis, valueDecimals);
     }
 
     public byte[] pieChart(String valueSuffix, List<ChartCategory> categories,
@@ -1115,6 +1117,14 @@
         return total;
     }
 
+    static int scaleLineChartHeight(int height) {
+        return (int) Math.round(height * LINE_CHART_HEIGHT_SCALE);
+    }
+
+    static long scaleLineChartHeight(long height) {
+        return Math.round(height * LINE_CHART_HEIGHT_SCALE);
+    }
+
     static BigDecimal displayValue(BigDecimal value, boolean percentItemLabels, int valueDecimals) {
         if (value == null) return null;
         int scale = percentItemLabels ? PERCENT_ITEM_LABEL_DECIMALS + 2 : valueDecimals;
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendService.java b/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendService.java
index 0e35898..9960464 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendService.java
@@ -64,12 +64,12 @@
                 prefix + "鍏ㄧ渷璺ㄥ尯鍩熶汉鍛樻祦鍔ㄩ噺鎯呭喌",
                 chartService.lineChart("涓囦汉娆�",
                         series(years, yearData, item -> item.totalDaily), false, 1100, 715),
-                new HolidayTrendWordService.ImageSize(5268595L, 3424555L)));
+                lineImageSize(5268595L, 3424555L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熺疮璁¤法鍖哄煙浜哄憳娴佸姩閲忚蛋鍔�",
                 chartService.lineChart("涓囦汉娆�",
                         series(years, yearData, item -> item.totalCumulative), false, 1100, 590),
-                new HolidayTrendWordService.ImageSize(5268595L, 2821305L)));
+                lineImageSize(5268595L, 2821305L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熷悇浜ら�氳繍杈撴柟寮忓杩愰噺鍗犳瘮鎯呭喌",
                 chartService.pieChart("浜烘", selected.modalShare(), 1000, 607), true,
@@ -80,44 +80,44 @@
                 "鈥�" + holidayLabel + "鈥濆亣鏈熻嚜椹惧嚭琛岄噺鎯呭喌",
                 chartService.lineChart("涓囦汉娆�",
                         series(years, yearData, item -> item.selfDrivingPersonFlow), false, 1100, 522),
-                new HolidayTrendWordService.ImageSize(5232400L, 2484120L)));
+                lineImageSize(5232400L, 2484120L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熼搧璺杩愰噺鎯呭喌",
                 chartService.lineChart("涓囦汉娆�",
                         series(years, yearData, item -> item.rail), false, 1100, 445),
-                new HolidayTrendWordService.ImageSize(5264785L, 2129155L)));
+                lineImageSize(5264785L, 2129155L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熸按璺杩愰噺鎯呭喌",
                 chartService.lineChart("涓囦汉娆�",
                         series(years, yearData, item -> item.water), false, 1100, 433),
-                new HolidayTrendWordService.ImageSize(5274310L, 2075815L)));
+                lineImageSize(5274310L, 2075815L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熸皯鑸杩愰噺鎯呭喌",
                 chartService.lineChart("涓囦汉娆�",
                         series(years, yearData, item -> item.civilAviation), false, 1100, 521),
-                new HolidayTrendWordService.ImageSize(5271135L, 2496185L)));
+                lineImageSize(5271135L, 2496185L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熼亾璺杩愰噺鎯呭喌",
                 chartService.lineChart("涓囦汉娆�",
                         series(years, yearData, item -> item.road), false, 1100, 590),
-                new HolidayTrendWordService.ImageSize(5268595L, 2821305L)));
+                lineImageSize(5268595L, 2821305L)));
 
         blocks.add(new HolidayTrendWordService.SectionBlock("涓夈�佽溅娴侀噺璧板娍"));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熼珮閫熷叕璺溅娴侀噺鎯呭喌",
                 chartService.lineChart("涓囪締娆�",
                         series(years, yearData, item -> item.expressway), false, 1100, 590),
-                new HolidayTrendWordService.ImageSize(5268595L, 2821305L)));
+                lineImageSize(5268595L, 2821305L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熸櫘閫氬浗鐪侀亾杞︽祦閲忔儏鍐�",
                 chartService.lineChart("涓囪締娆�",
                         series(years, yearData, item -> item.nationalProvincial), false, 1100, 590),
-                new HolidayTrendWordService.ImageSize(5268595L, 2821305L)));
+                lineImageSize(5268595L, 2821305L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熷叏鐪佽溅娴佹�婚噺鎯呭喌",
                 chartService.lineChart("涓囪締娆�",
                         series(years, yearData, item -> item.totalVehicleFlow), false, 1100, 590),
-                new HolidayTrendWordService.ImageSize(5268595L, 2821305L)));
+                lineImageSize(5268595L, 2821305L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 "鈥�" + holidayLabel + "鈥濆亣鏈熷叕璺嚭琛岀粨鏋�",
                 chartService.stackedBarChart("涓囦汉娆�",
@@ -139,12 +139,12 @@
                 prefix + "鏅�氬浗鐪侀亾瑙傛祴绔欏钩鍧囨満鍔ㄨ溅閫熷害",
                 chartService.lineChart("鍏噷/灏忔椂",
                         Collections.singletonList(series("骞冲潎閫熷害", observation.speed)), false, 1100, 590),
-                new HolidayTrendWordService.ImageSize(5268595L, 2821305L)));
+                lineImageSize(5268595L, 2821305L)));
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 prefix + "鏅�氬浗鐪侀亾瑙傛祴绔欏钩鍧囨嫢鎸ゅ害",
                 chartService.lineChart("鎷ユ尋搴�",
                         Collections.singletonList(series("骞冲潎鎷ユ尋搴�", observation.congestion)), false, 1100, 590),
-                new HolidayTrendWordService.ImageSize(5268595L, 2821305L)));
+                lineImageSize(5268595L, 2821305L)));
 
         File template = resolveTemplateFile();
         if (!template.exists() || !template.isFile()) {
@@ -347,6 +347,11 @@
         return result;
     }
 
+    private HolidayTrendWordService.ImageSize lineImageSize(long width, long height) {
+        return new HolidayTrendWordService.ImageSize(
+                width, HolidayTrendChartService.scaleLineChartHeight(height));
+    }
+
     private File resolveTemplateFile() {
         List<File> candidates = new ArrayList<>();
         File configured = new File(trendTemplatePath);
diff --git a/traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendChartServiceTest.java b/traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendChartServiceTest.java
index 03cf0a1..fff727d 100644
--- a/traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendChartServiceTest.java
+++ b/traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendChartServiceTest.java
@@ -79,6 +79,22 @@
     }
 
     @Test
+    void scalesLineChartHeightForBetterVerticalSeparation() throws Exception {
+        HolidayTrendChartService service = new HolidayTrendChartService();
+        HolidayTrendChartService.ChartSeries series = new HolidayTrendChartService.ChartSeries();
+        series.setName("娴嬭瘯");
+        series.setValues(java.util.Arrays.asList(
+                new BigDecimal("1.00"), new BigDecimal("2.00"), new BigDecimal("3.00")));
+
+        byte[] png = service.lineChart("涓囦汉娆�",
+                java.util.Collections.singletonList(series), false, 1100, 590);
+        BufferedImage image = ImageIO.read(new ByteArrayInputStream(png));
+
+        assertNotNull(image);
+        assertEquals(HolidayTrendChartService.scaleLineChartHeight(590), image.getHeight());
+    }
+
+    @Test
     void rendersHigherPrecisionLineLabelsWhenRequested() {
         HolidayTrendChartService service = new HolidayTrendChartService();
         HolidayTrendChartService.ChartSeries congestion = new HolidayTrendChartService.ChartSeries();

--
Gitblit v1.9.1