From 4ac9254496a96740481904ceb022c1a9015a262c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=8E=E4=BD=97?= Date: Mon, 1 Jun 2026 14:35:17 +0800 Subject: [PATCH] =?UTF-8?q?fix(#634):=20=E8=AF=B7=E4=BF=AE=E5=A4=8D=20Bug?= =?UTF-8?q?=20#634:=20web=5Fui=20=E6=89=8B=E5=8A=A8=E5=85=A5=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: - ** - `core-framework/.../ApplicationConfig.java:39` — `LocalDateTimeDeserializer` 只配置了 `yyyy-MM-dd HH:mm:ss` 格式 - 前端发送 ISO 8601 格式日期字符串 `"2026-06-01T01:45:06.439Z"`(含毫秒 + `Z` 时区后缀),Jackson 反序列化失败抛出 `JsonParseException` 修复: - ** - 修改 `ApplicationConfig.java`,将单一格式的 `LocalDateTimeDeserializer` 替换为自定义多格式反序列化器 - 新反序列化器依次尝试:ISO 8601(`yyyy-MM-ddTHH:mm:ss.SSS`)→ 简单格式(`yyyy-MM-dd HH:mm:ss`)→ 斜杠格式(`yyyy/M/d HH:mm:ss`) - 自动剥离 `Z`/`z` 时区后缀和 `+HH:MM` 偏移量(`LocalDateTime` 不含时区信息) - 6 环验证:** - ①前端 → ②Controller:`@RequestBody` 反序列化现在支持 ISO 8601 格式 ✅ - ③Service:无需修改,DTO 字段类型未变 ✅ - ④Mapper:无需修改,SQL 映射未变 ✅ - ⑤DB:无需修改,字段类型未变 ✅ - ⑥关联模块:全局生效,所有使用 `LocalDateTime` 的实体均受益 ✅ - 编译验证:** `mvn compile -pl openhis-application -am` → BUILD SUCCESS ✅ - 变更文件:** `core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java` --- .../framework/config/ApplicationConfig.java | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/openhis-server-new/core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java b/openhis-server-new/core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java index a36d518ad..df5edb701 100755 --- a/openhis-server-new/core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java +++ b/openhis-server-new/core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java @@ -1,7 +1,9 @@ package com.core.framework.config; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; @@ -9,6 +11,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; +import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.TimeZone; @@ -24,6 +27,36 @@ import java.util.TimeZone; // 指定要扫描的Mapper类的包的路径 @MapperScan({"com.core.**.mapper", "com.openhis.**.mapper"}) public class ApplicationConfig { + + /** 支持多种日期格式的反序列化器 */ + private static final JsonDeserializer LOCAL_DATE_TIME_DESERIALIZER = new JsonDeserializer() { + private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + private static final DateTimeFormatter SIMPLE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + private static final DateTimeFormatter SLASH_FORMATTER = DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss"); + + @Override + public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + String text = p.getText(); + if (text == null || text.isEmpty()) { + return null; + } + // 去除时区后缀 Z/z 和偏移量 +HH:MM/+HHMM(LocalDateTime 不含时区信息) + String cleaned = text.replaceAll("[Zz]$", "").replaceAll("[+-]\\d{2}:?\\d{2}$", ""); + // 尝试 ISO 8601 格式(yyyy-MM-ddTHH:mm:ss.SSS) + try { + return LocalDateTime.parse(cleaned, ISO_FORMATTER); + } catch (Exception ignored) { + } + // 尝试简单格式(yyyy-MM-dd HH:mm:ss) + try { + return LocalDateTime.parse(cleaned, SIMPLE_FORMATTER); + } catch (Exception ignored) { + } + // 尝试斜杠格式(yyyy/M/d HH:mm:ss) + return LocalDateTime.parse(cleaned, SLASH_FORMATTER); + } + }; + /** * 时区配置 */ @@ -36,7 +69,7 @@ public class ApplicationConfig { builder.simpleDateFormat("yyyy/M/d HH:mm:ss"); // 添加JavaTimeModule支持,用于LocalDateTime JavaTimeModule javaTimeModule = new JavaTimeModule(); - javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + javaTimeModule.addDeserializer(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER); builder.modules(javaTimeModule); builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss"))); };