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 尺寸

---
 traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayVehicleAdjustmentService.java |  177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 177 insertions(+), 0 deletions(-)

diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayVehicleAdjustmentService.java b/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayVehicleAdjustmentService.java
new file mode 100644
index 0000000..7823197
--- /dev/null
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/holiday/service/HolidayVehicleAdjustmentService.java
@@ -0,0 +1,177 @@
+package com.trafficaudit.holiday.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.trafficaudit.holiday.HolidayConstants;
+import com.trafficaudit.holiday.HolidayNumberUtils;
+import com.trafficaudit.holiday.entity.HolidayVehicleAdjustment;
+import com.trafficaudit.holiday.entity.HolidayVehicleFlow;
+import com.trafficaudit.holiday.mapper.HolidayVehicleFlowMapper;
+import com.trafficaudit.holiday.mapper.HolidayVehicleAdjustmentMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Service
+public class HolidayVehicleAdjustmentService {
+
+    private static final int REASON_MAX_LENGTH = 500;
+
+    @Resource
+    private HolidayVehicleAdjustmentMapper adjustmentMapper;
+    @Resource
+    private HolidayVehicleFlowMapper vehicleFlowMapper;
+
+    public List<HolidayVehicleAdjustment> list(Integer year) {
+        List<HolidayVehicleAdjustment> rows = adjustmentMapper.selectList(
+                new LambdaQueryWrapper<HolidayVehicleAdjustment>()
+                        .eq(year != null, HolidayVehicleAdjustment::getYear, year)
+                        .orderByDesc(HolidayVehicleAdjustment::getYear)
+                        .orderByAsc(HolidayVehicleAdjustment::getFlowDate));
+        if (rows.isEmpty()) return rows;
+
+        Set<Integer> years = new HashSet<>();
+        for (HolidayVehicleAdjustment row : rows) {
+            if (row.getYear() != null) years.add(row.getYear());
+        }
+        if (years.isEmpty()) return rows;
+
+        List<HolidayVehicleFlow> sourceRows = vehicleFlowMapper.selectList(
+                new LambdaQueryWrapper<HolidayVehicleFlow>()
+                        .eq(HolidayVehicleFlow::getRoadCategory, HolidayConstants.ROAD_NATIONAL_PROVINCIAL)
+                        .eq(HolidayVehicleFlow::getVehicleType, HolidayConstants.VEHICLE_MEDIUM_SMALL_PASSENGER)
+                        .in(HolidayVehicleFlow::getYear, years));
+        Map<String, BigDecimal> originalValues = new HashMap<>();
+        for (HolidayVehicleFlow sourceRow : sourceRows) {
+            if (sourceRow.getYear() == null || sourceRow.getFlowDate() == null || sourceRow.getVehicleCount() == null) {
+                continue;
+            }
+            originalValues.put(sourceKey(sourceRow.getYear(), sourceRow.getFlowDate()), sourceRow.getVehicleCount());
+        }
+        for (HolidayVehicleAdjustment row : rows) {
+            if (row.getYear() != null && row.getFlowDate() != null) {
+                row.setOriginalValue(originalValues.get(sourceKey(row.getYear(), row.getFlowDate())));
+            }
+        }
+        return rows;
+    }
+
+    public BigDecimal findOriginalValue(Integer year, LocalDate flowDate) {
+        if (year == null || flowDate == null || flowDate.getYear() != year) {
+            throw new IllegalArgumentException("骞翠唤鍜屾棩鏈熶笉姝g‘");
+        }
+        HolidayVehicleFlow sourceRow = vehicleFlowMapper.selectOne(
+                new LambdaQueryWrapper<HolidayVehicleFlow>()
+                        .eq(HolidayVehicleFlow::getYear, year)
+                        .eq(HolidayVehicleFlow::getFlowDate, flowDate)
+                        .eq(HolidayVehicleFlow::getRoadCategory, HolidayConstants.ROAD_NATIONAL_PROVINCIAL)
+                        .eq(HolidayVehicleFlow::getVehicleType, HolidayConstants.VEHICLE_MEDIUM_SMALL_PASSENGER)
+                        .last("limit 1"));
+        return sourceRow == null ? null : sourceRow.getVehicleCount();
+    }
+
+    @Transactional
+    public HolidayVehicleAdjustment save(Map<String, Object> params) {
+        Long id = longValue(params.get("id"));
+        Integer year = intValue(params.get("year"));
+        LocalDate flowDate = dateValue(params.get("flowDate"));
+        BigDecimal adjustedValue = decimalValue(params.get("adjustedValue"));
+        String reason = textValue(params.get("reason"));
+
+        if (year == null || year < 2000 || year > 2100) {
+            throw new IllegalArgumentException("骞翠唤涓嶆纭�");
+        }
+        if (year >= LocalDate.now().getYear()) {
+            throw new IllegalArgumentException("寰�骞村浗鐪侀亾鏁版嵁璋冩暣浠呯淮鎶ゅ巻鍙插勾浠�");
+        }
+        if (flowDate == null || flowDate.getYear() != year) {
+            throw new IllegalArgumentException("鏃ユ湡蹇呴』灞炰簬鎵�閫夊勾浠�");
+        }
+        if (adjustedValue == null || adjustedValue.compareTo(BigDecimal.ZERO) < 0) {
+            throw new IllegalArgumentException("璋冩暣鍚庣殑鍥界渷閬撹溅娴侀噺涓嶈兘灏忎簬 0");
+        }
+        if (reason.isEmpty()) {
+            throw new IllegalArgumentException("璋冩暣鍘熷洜涓嶈兘涓虹┖");
+        }
+        if (reason.length() > REASON_MAX_LENGTH) {
+            throw new IllegalArgumentException("璋冩暣鍘熷洜涓嶈兘瓒呰繃 " + REASON_MAX_LENGTH + " 涓瓧绗�");
+        }
+
+        HolidayVehicleAdjustment sameKey = adjustmentMapper.selectOne(
+                new LambdaQueryWrapper<HolidayVehicleAdjustment>()
+                        .eq(HolidayVehicleAdjustment::getYear, year)
+                        .eq(HolidayVehicleAdjustment::getFlowDate, flowDate)
+                        .last("limit 1"));
+        HolidayVehicleAdjustment entity;
+        if (id == null) {
+            entity = sameKey == null ? new HolidayVehicleAdjustment() : sameKey;
+        } else {
+            entity = adjustmentMapper.selectById(id);
+            if (entity == null) {
+                throw new IllegalArgumentException("璋冩暣璁板綍涓嶅瓨鍦�");
+            }
+            if (sameKey != null && !sameKey.getId().equals(id)) {
+                throw new IllegalArgumentException("璇ュ勾浠藉拰鏃ユ湡宸插瓨鍦ㄨ皟鏁磋褰�");
+            }
+        }
+
+        if (entity.getId() == null) {
+            entity.setCreatedAt(LocalDateTime.now());
+        }
+        entity.setYear(year);
+        entity.setFlowDate(flowDate);
+        entity.setAdjustedValue(HolidayNumberUtils.normalize(adjustedValue));
+        entity.setReason(reason);
+        entity.setUpdatedAt(LocalDateTime.now());
+        if (entity.getId() == null) {
+            adjustmentMapper.insert(entity);
+        } else {
+            adjustmentMapper.updateById(entity);
+        }
+        return entity;
+    }
+
+    @Transactional
+    public void delete(Long id) {
+        if (id == null) {
+            throw new IllegalArgumentException("缂哄皯璁板綍 id");
+        }
+        adjustmentMapper.deleteById(id);
+    }
+
+    private String sourceKey(Integer year, LocalDate flowDate) {
+        return year + "|" + flowDate;
+    }
+
+    private Long longValue(Object value) {
+        if (value == null || value.toString().trim().isEmpty()) return null;
+        return Long.valueOf(value.toString().trim());
+    }
+
+    private Integer intValue(Object value) {
+        if (value == null || value.toString().trim().isEmpty()) return null;
+        return Integer.valueOf(value.toString().trim());
+    }
+
+    private BigDecimal decimalValue(Object value) {
+        if (value == null || value.toString().trim().isEmpty()) return null;
+        return HolidayNumberUtils.decimalValue(value);
+    }
+
+    private LocalDate dateValue(Object value) {
+        if (value == null || value.toString().trim().isEmpty()) return null;
+        return LocalDate.parse(value.toString().trim());
+    }
+
+    private String textValue(Object value) {
+        return value == null ? "" : value.toString().trim();
+    }
+}

--
Gitblit v1.9.1