From 73e810fc9569597be99accd08d63aab6e7c0daac Mon Sep 17 00:00:00 2001
From: xyc <jc_xiong@hotmail.com>
Date: 星期二, 06 十月 2026 09:36:41 +0800
Subject: [PATCH] fix(holiday): 提高平均拥挤度走势图标签精度

---
 HANDOFF.md                                                                                            |    8 ++++++++
 traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendChartService.java     |   27 +++++++++++++++++----------
 traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayTrendService.java          |    2 +-
 traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendChartServiceTest.java |   21 +++++++++++++++++++++
 4 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/HANDOFF.md b/HANDOFF.md
index cd15b68..97f9148 100644
--- a/HANDOFF.md
+++ b/HANDOFF.md
@@ -6,6 +6,14 @@
 
 ## 鏈�鏂帮紙2026-10-06锛�
 
+### 10-06锛氳娴嬬珯骞冲潎鎷ユ尋搴﹁蛋鍔垮浘鏀逛负 3 浣嶅皬鏁�
+
+- **闂**锛氱敤鎴峰鍏� 10-05 瑙傛祴绔欐暟鎹悗鍙嶉锛屾渶鍚庝竴寮犳嫢鎸ゅ害鍥句腑 10-04銆�10-05 鏍囩閮芥樉绀� `0.49`锛屼絾鐐逛綅楂樺害涓嶅悓銆�
+- **鏍瑰洜**锛氬钩鍧囨嫢鎸ゅ害鍘熷�煎垎鍒负 `0.490890014472` 鍜� `0.492414492754`锛屾姌绾挎寜鏈彇鏁村師鍊肩粯鍒讹紝鏍囩鍘熶负鏈�澶� 2 浣嶅皬鏁帮紝瀵艰嚧鏍囩绮惧害涓庡浘褰㈢簿搴︿笉涓�鑷达紝涓嶆槸鏃ユ眹鎬绘垨鐐逛綅璁$畻閿欒銆�
+- **淇**锛歚HolidayTrendChartService.lineChart` 鏂板鍙�� `valueDecimals`锛岄粯璁や粛涓� 2锛涗粎鈥滄櫘閫氬浗鐪侀亾瑙傛祴绔欏钩鍧囨嫢鎸ゅ害鈥濆浘浼� 3 浣嶃��10-04銆�10-05 鐜板湪鍒嗗埆鏄剧ず `0.491`銆乣0.492`锛屽叾浣欏浘鍙e緞涓嶅彉銆�
+- **楠岃瘉**锛氬悗绔叏閲� `mvn -q test -f traffic-audit-server\pom.xml` 閫氳繃锛涢噸鍚悗鍙鐢熸垚鏂� DOCX锛孫CR 鏍囩涓� `0.504/0.476/0.467/0.491/0.492`锛涗笌鐢ㄦ埛鎻愪緵鐨勬枃妗i�愬浘姣斿锛�15 寮犲浘涓粎鎷ユ尋搴﹀浘 `image15` 鍙樺寲锛屽叾浠� 14 寮� SHA-256 瀹屽叏涓�鑷淬�傛祴璇曟姤鍛婏細`docs/鍔熻兘娴嬭瘯鎶ュ憡/鍔熻兘娴嬭瘯鎶ュ憡_鎷ユ尋搴﹁蛋鍔垮浘绮惧害_2026-10-06.md`锛堟湰鍦扮暀瀛橈紝涓嶅叆搴擄級銆�
+- **鏁版嵁杈圭晫**锛氭湭瀵煎叆銆佽鐩栨垨閲嶅浠讳綍涓氬姟鏁版嵁銆�
+
 ### 10-06锛氬線骞村浗鐪侀亾璋冩暣鍒楄〃琛ュ厖璋冩暣鍓嶅��
 
 - **鏀瑰姩**锛氳皟鏁村垪琛ㄦ帴鍙e湪鍚屼竴骞翠唤銆佸悓涓�鏃ユ湡銆佹櫘閫氬浗鐪侀亾鍙e緞涓嬶紝浠� `holiday_vehicle_flow` 琛ヨ繑鍥� `originalValue`锛涙病鏈夊師濮嬭褰曟椂淇濇寔绌猴紝椤甸潰涓嶆樉绀哄崰浣嶇銆傝〃鏍兼柊澧炩�滆皟鏁村墠鍥界渷閬撹溅娴侀噺锛堜竾杈嗘锛夆�濓紝鍘熲�滆皟鏁村悗鍥界渷閬撹溅娴佲�濇敼涓衡�滆皟鏁村悗鍥界渷閬撹溅娴侀噺鈥濄��
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 4343f08..e0b9c88 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
@@ -95,6 +95,11 @@
 
     public byte[] lineChart(String yAxisLabel, List<ChartSeries> series, boolean percentAxis,
                             int width, int height) {
+        return lineChart(yAxisLabel, series, percentAxis, 2, width, height);
+    }
+
+    public byte[] lineChart(String yAxisLabel, List<ChartSeries> series, boolean percentAxis,
+                            int valueDecimals, int width, int height) {
         XYSeriesCollection dataset = new XYSeriesCollection();
         for (int seriesIndex = 0; seriesIndex < series.size(); seriesIndex++) {
             ChartSeries item = series.get(seriesIndex);
@@ -148,7 +153,7 @@
         }
         NumberFormat valueFormat = percentAxis
                 ? NumberFormat.getPercentInstance() : new DecimalFormat("#,##0.##");
-        valueFormat.setMaximumFractionDigits(percentAxis ? 0 : 2);
+        valueFormat.setMaximumFractionDigits(percentAxis ? 0 : valueDecimals);
         rangeAxis.setNumberFormatOverride(valueFormat);
         plot.setRangeAxis(rangeAxis);
         plot.setAxisOffset(new RectangleInsets(2.0, 2.0, 2.0, 2.0));
@@ -166,7 +171,7 @@
                     BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
         }
         plot.setRenderer(renderer);
-        return render(chart, width, height, yAxisLabel, true, percentAxis);
+        return render(chart, width, height, yAxisLabel, true, percentAxis, valueDecimals);
     }
 
     public byte[] pieChart(String valueSuffix, List<ChartCategory> categories,
@@ -212,7 +217,7 @@
         for (ChartCategory category : categories) {
             plot.setSectionPaint(category.getName(), seriesColor(index++));
         }
-        return render(chart, width, height, valueSuffix, false, false);
+        return render(chart, width, height, valueSuffix, false, false, 2);
     }
 
     public byte[] stackedBarChart(String yAxisLabel, List<String> categories,
@@ -282,7 +287,7 @@
             renderer.setSeriesPaint(i, seriesColor(i));
         }
         plot.setRenderer(renderer);
-        return render(chart, width, height, yAxisLabel, true, percentAxis);
+        return render(chart, width, height, yAxisLabel, true, percentAxis, 2);
     }
 
     private static class WaterRightPiePlot<K extends Comparable<K>> extends PiePlot<K> {
@@ -445,7 +450,7 @@
     }
 
     private byte[] render(JFreeChart chart, int width, int height, String unitLabel,
-                         boolean axisChart, boolean percentItemLabels) {
+                         boolean axisChart, boolean percentItemLabels, int valueDecimals) {
         try {
             reserveUnitLabelBand(chart, axisChart, unitLabel);
             ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -465,7 +470,7 @@
                     drawDateLabel(graphics, info.getPlotInfo().getDataArea());
                 }
                 drawXYItemLabels(graphics, image, chart,
-                        info.getPlotInfo().getDataArea(), percentItemLabels, unitLabel);
+                        info.getPlotInfo().getDataArea(), percentItemLabels, unitLabel, valueDecimals);
                 drawStackedBarLabels(graphics, image, chart,
                         info.getPlotInfo().getDataArea(), percentItemLabels);
             } finally {
@@ -830,7 +835,7 @@
 
     private void drawXYItemLabels(Graphics2D graphics, BufferedImage image, JFreeChart chart,
                                   Rectangle2D dataArea, boolean percentItemLabels,
-                                  String unitLabel) {
+                                  String unitLabel, int valueDecimals) {
         if (!(chart.getPlot() instanceof XYPlot) || dataArea == null
                 || dataArea.getWidth() <= 0 || dataArea.getHeight() <= 0) {
             return;
@@ -859,7 +864,7 @@
                 Point2D point = itemPoint(plot, dataset, seriesIndex, itemIndex, dataArea);
                 if (yValue == null || point == null) continue;
                 labels.add(new DayLabel(seriesIndex, point,
-                        formatLineLabel(yValue, percentItemLabels)));
+                        formatLineLabel(yValue, percentItemLabels, valueDecimals)));
             }
             // A day's labels are stacked in the same top-to-bottom order as its data
             // points, so a label never looks attached to a neighbouring line.
@@ -1108,13 +1113,15 @@
         return total;
     }
 
-    private String formatLineLabel(Number value, boolean percentItemLabels) {
+    private String formatLineLabel(Number value, boolean percentItemLabels, int valueDecimals) {
         if (percentItemLabels) {
             NumberFormat formatter = NumberFormat.getPercentInstance();
             formatter.setMaximumFractionDigits(1);
             return formatter.format(value.doubleValue());
         }
-        return new DecimalFormat("#,##0.##").format(value.doubleValue());
+        DecimalFormat formatter = new DecimalFormat("#,##0");
+        formatter.setMaximumFractionDigits(valueDecimals);
+        return formatter.format(value.doubleValue());
     }
 
     private void drawLabelWithHalo(Graphics2D graphics, String text, Rectangle2D rectangle,
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..39b61d4 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
@@ -143,7 +143,7 @@
         blocks.add(new HolidayTrendWordService.ChartBlock(
                 prefix + "鏅�氬浗鐪侀亾瑙傛祴绔欏钩鍧囨嫢鎸ゅ害",
                 chartService.lineChart("鎷ユ尋搴�",
-                        Collections.singletonList(series("骞冲潎鎷ユ尋搴�", observation.congestion)), false, 1100, 590),
+                        Collections.singletonList(series("骞冲潎鎷ユ尋搴�", observation.congestion)), false, 3, 1100, 590),
                 new HolidayTrendWordService.ImageSize(5268595L, 2821305L)));
 
         File template = resolveTemplateFile();
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 e705637..29a8ff1 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
@@ -6,6 +6,7 @@
 import java.awt.image.BufferedImage;
 import java.io.ByteArrayInputStream;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -40,6 +41,26 @@
         assertNoLargeLightGrayBackground(stacked);
     }
 
+    @Test
+    void rendersHigherPrecisionLineLabelsWhenRequested() {
+        HolidayTrendChartService service = new HolidayTrendChartService();
+        HolidayTrendChartService.ChartSeries congestion = new HolidayTrendChartService.ChartSeries();
+        congestion.setName("骞冲潎鎷ユ尋搴�");
+        congestion.setValues(java.util.Arrays.asList(
+                new java.math.BigDecimal("0.467029"),
+                new java.math.BigDecimal("0.490890"),
+                new java.math.BigDecimal("0.492414")));
+
+        byte[] twoDecimals = service.lineChart("鎷ユ尋搴�",
+                java.util.Collections.singletonList(congestion), false, 2, 1100, 590);
+        byte[] threeDecimals = service.lineChart("鎷ユ尋搴�",
+                java.util.Collections.singletonList(congestion), false, 3, 1100, 590);
+
+        assertPng(twoDecimals);
+        assertPng(threeDecimals);
+        assertFalse(java.util.Arrays.equals(twoDecimals, threeDecimals));
+    }
+
     private void assertNoLargeLightGrayBackground(byte[] data) throws Exception {
         BufferedImage image = ImageIO.read(new ByteArrayInputStream(data));
         int matches = 0;

--
Gitblit v1.9.1