✨ 小程序用户独立为 blade_mp_user,并兼容司机/车辆 OCR 宽松日期
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+148
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.jackson;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* LocalDate 宽松反序列化,对齐 OCR / 司机侧日期归一化规则。
|
||||
* <p>
|
||||
* 兼容写法:
|
||||
* <ul>
|
||||
* <li>ISO:{@code yyyy-MM-dd}</li>
|
||||
* <li>紧凑:{@code yyyyMMdd}</li>
|
||||
* <li>点分 / 斜杠 / 年月日:{@code 2018.3.9}、{@code 2026/03/17}、{@code 2030年05月20日}</li>
|
||||
* <li>任意非数字分隔:年与月、月与日之间只要不是数字即可</li>
|
||||
* <li>区间文本:按字段名取起期(first)或止期(last)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class FlexibleLocalDateDeserializer extends JsonDeserializer<LocalDate> {
|
||||
|
||||
/**
|
||||
* 4 位年 + 1~2 位月 + 1~2 位日,中间允许任意非数字分隔(与 OcrFieldSupport 一致)
|
||||
*/
|
||||
private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4})\\D+(\\d{1,2})\\D+(\\d{1,2})");
|
||||
|
||||
private static final Pattern COMPACT_PATTERN = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})");
|
||||
|
||||
@Override
|
||||
public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException {
|
||||
String text = parser.getValueAsString();
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
String value = text.trim();
|
||||
if (value.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// 「长期」等非日期文案:按空值处理,避免把无法解析的字符串打成 400
|
||||
if (value.contains("长期") || value.contains("永久")) {
|
||||
return null;
|
||||
}
|
||||
boolean preferLast = isEndDateField(parser.getCurrentName());
|
||||
LocalDate parsed = parseFlexible(value, preferLast);
|
||||
if (parsed != null) {
|
||||
return parsed;
|
||||
}
|
||||
return (LocalDate) context.handleWeirdStringValue(LocalDate.class, value,
|
||||
"期望日期格式 yyyy-MM-dd / yyyyMMdd / yyyy年M月d日 等 OCR 常见写法");
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析宽松日期文本;区间时按 preferLast 取首段或末段。
|
||||
*
|
||||
* @param value 原始文本
|
||||
* @param preferLast true 取止期,false 取起期
|
||||
* @return 合法 LocalDate;无法识别时返回 null
|
||||
*/
|
||||
public static LocalDate parseFlexible(String value, boolean preferLast) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String text = value.trim();
|
||||
if (text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
List<LocalDate> candidates = matchDates(text);
|
||||
if (!candidates.isEmpty()) {
|
||||
return preferLast ? candidates.get(candidates.size() - 1) : candidates.get(0);
|
||||
}
|
||||
// 去掉所有非数字后恰为 8 位时按 yyyyMMdd 处理(如 20260317、2026-0317 混杂)
|
||||
String compact = text.replaceAll("\\D", "");
|
||||
if (compact.length() == 8) {
|
||||
return toLocalDate(compact.substring(0, 4), compact.substring(4, 6), compact.substring(6, 8));
|
||||
}
|
||||
Matcher compactMatcher = COMPACT_PATTERN.matcher(text);
|
||||
if (compactMatcher.find()) {
|
||||
return toLocalDate(compactMatcher.group(1), compactMatcher.group(2), compactMatcher.group(3));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<LocalDate> matchDates(String text) {
|
||||
List<LocalDate> dates = new ArrayList<>();
|
||||
Matcher matcher = DATE_PATTERN.matcher(text);
|
||||
while (matcher.find()) {
|
||||
LocalDate date = toLocalDate(matcher.group(1), matcher.group(2), matcher.group(3));
|
||||
if (date != null) {
|
||||
dates.add(date);
|
||||
}
|
||||
}
|
||||
return dates;
|
||||
}
|
||||
|
||||
private static LocalDate toLocalDate(String yearText, String monthText, String dayText) {
|
||||
try {
|
||||
int year = Integer.parseInt(yearText);
|
||||
int month = Integer.parseInt(monthText);
|
||||
int day = Integer.parseInt(dayText);
|
||||
return LocalDate.of(year, month, day);
|
||||
} catch (NumberFormatException | DateTimeException exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 止期字段名通常以 End / EndDate 结尾,区间文本应取最后一段日期。
|
||||
*/
|
||||
private static boolean isEndDateField(String fieldName) {
|
||||
if (fieldName == null || fieldName.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return fieldName.endsWith("End") || fieldName.endsWith("EndDate")
|
||||
|| fieldName.contains("EndDate") || fieldName.contains("ValidEnd");
|
||||
}
|
||||
|
||||
}
|
||||
+11
-2
@@ -29,12 +29,14 @@ import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springblade.core.tenant.mp.TenantEntity;
|
||||
import org.springblade.transport.jackson.FlexibleLocalDateDeserializer;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDate;
|
||||
@@ -67,6 +69,7 @@ public class Driver extends TenantEntity {
|
||||
* 出生年月
|
||||
*/
|
||||
@Schema(description = "出生年月")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate birthday;
|
||||
/**
|
||||
* 性别
|
||||
@@ -118,11 +121,13 @@ public class Driver extends TenantEntity {
|
||||
* 身份证有效期起
|
||||
*/
|
||||
@Schema(description = "身份证有效期起")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate idCardValidStart;
|
||||
/**
|
||||
* 身份证有效期止
|
||||
*/
|
||||
@Schema(description = "身份证有效期止")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate idCardValidEnd;
|
||||
/**
|
||||
* 身份证长期有效
|
||||
@@ -148,11 +153,13 @@ public class Driver extends TenantEntity {
|
||||
* 驾驶证有效期起
|
||||
*/
|
||||
@Schema(description = "驾驶证有效期起")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate drivingLicenseStartDate;
|
||||
/**
|
||||
* 驾驶证有效期止
|
||||
*/
|
||||
@Schema(description = "驾驶证有效期止")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate drivingLicenseEndDate;
|
||||
/**
|
||||
* 驾驶证长期有效
|
||||
@@ -183,6 +190,7 @@ public class Driver extends TenantEntity {
|
||||
* 从业资格证有效期止
|
||||
*/
|
||||
@Schema(description = "从业资格证有效期止")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate qualificationEndDate;
|
||||
/**
|
||||
* 从业资格证长期有效
|
||||
@@ -210,9 +218,10 @@ public class Driver extends TenantEntity {
|
||||
@Schema(description = "手机号")
|
||||
private String mobile;
|
||||
/**
|
||||
* 关联系统用户ID
|
||||
* 关联小程序用户ID(blade_mp_user.id)
|
||||
*/
|
||||
@Schema(description = "关联系统用户ID")
|
||||
@Schema(description = "关联小程序用户ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long userId;
|
||||
/**
|
||||
* 与联系人关系
|
||||
|
||||
+9
@@ -27,12 +27,14 @@ package org.springblade.transport.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springblade.core.tenant.mp.TenantEntity;
|
||||
import org.springblade.transport.jackson.FlexibleLocalDateDeserializer;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDate;
|
||||
@@ -125,6 +127,7 @@ public class TransportVehicle extends TenantEntity {
|
||||
* 强制报废日期
|
||||
*/
|
||||
@Schema(description = "强制报废日期")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate compulsoryScrapDate;
|
||||
/**
|
||||
* 强制报废长期有效
|
||||
@@ -145,11 +148,13 @@ public class TransportVehicle extends TenantEntity {
|
||||
* 行驶证有效期起
|
||||
*/
|
||||
@Schema(description = "行驶证有效期起")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate drivingLicenseStartDate;
|
||||
/**
|
||||
* 行驶证有效期止
|
||||
*/
|
||||
@Schema(description = "行驶证有效期止")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate drivingLicenseEndDate;
|
||||
/**
|
||||
* 行驶证长期有效
|
||||
@@ -185,11 +190,13 @@ public class TransportVehicle extends TenantEntity {
|
||||
* 道路运输证有效期起
|
||||
*/
|
||||
@Schema(description = "道路运输证有效期起")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate roadTransportCertStartDate;
|
||||
/**
|
||||
* 道路运输证有效期止
|
||||
*/
|
||||
@Schema(description = "道路运输证有效期止")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate roadTransportCertEndDate;
|
||||
/**
|
||||
* 道路运输证长期有效
|
||||
@@ -205,6 +212,7 @@ public class TransportVehicle extends TenantEntity {
|
||||
* 道路运输年审有效期
|
||||
*/
|
||||
@Schema(description = "道路运输年审有效期")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate annualReviewEndDate;
|
||||
/**
|
||||
* 道路运输年审长期有效
|
||||
@@ -220,6 +228,7 @@ public class TransportVehicle extends TenantEntity {
|
||||
* 机动车登记日期
|
||||
*/
|
||||
@Schema(description = "机动车登记日期")
|
||||
@JsonDeserialize(using = FlexibleLocalDateDeserializer.class)
|
||||
private LocalDate registrationDate;
|
||||
/**
|
||||
* 机动车登记本图片
|
||||
|
||||
Reference in New Issue
Block a user