diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/PersonCertSubmitRequest.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/PersonCertSubmitRequest.java index c33d030f..01cc4f53 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/PersonCertSubmitRequest.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/PersonCertSubmitRequest.java @@ -51,6 +51,12 @@ public class PersonCertSubmitRequest implements Serializable { private String realName; @Schema(description = "身份证号") private String idCardNo; + @Schema(description = "出生年月") + private LocalDate birthday; + @Schema(description = "住址-区划:省市区名称拼接串") + private String addressRegion; + @Schema(description = "住址-详细地址") + private String address; @Schema(description = "身份证正面照") private String idCardFrontUrl; @Schema(description = "身份证反面照") diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CertAuditServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CertAuditServiceImpl.java index 09a6ece6..247239d0 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CertAuditServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CertAuditServiceImpl.java @@ -354,6 +354,10 @@ public class CertAuditServiceImpl implements ICertAuditService { requireIdCardNotTaken(snapshot.getIdCardNo(), driver.getId()); driver.setDriverName(snapshot.getRealName()); driver.setIdCardNo(snapshot.getIdCardNo()); + driver.setBirthday(snapshot.getBirthday()); + // 空串不是「没填」:框架的 not_null 策略只跳过 null,写空串会把管理端填过的住址清掉 + driver.setAddressRegion(blankToNull(snapshot.getAddressRegion())); + driver.setAddress(blankToNull(snapshot.getAddress())); driver.setIdCardFront(snapshot.getIdCardFrontUrl()); driver.setIdCardBack(snapshot.getIdCardBackUrl()); driver.setIdCardValidStart(snapshot.getIdCardValidStart()); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/OcrFieldSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/OcrFieldSupport.java index ef4e7798..74184e28 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/OcrFieldSupport.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/OcrFieldSupport.java @@ -279,6 +279,10 @@ public final class OcrFieldSupport { Map> aliases = new LinkedHashMap<>(); aliases.put("realName", List.of("姓名")); aliases.put("idCardNo", List.of("公民身份号码", "公民身份证号码", "身份证号", "身份证号码")); + // 身份证正面的「出生」是一整串日期(1990年1月1日),按 birthday 归一成 yyyy-MM-dd; + // 住址是身份证上的登记住址,写进 driver.address + aliases.put("birthday", List.of("出生", "出生年月", "出生日期")); + aliases.put("address", List.of("住址", "地址")); aliases.put("idCardValidStart", List.of("签发日期", "有效起始日期", "有效期限起")); aliases.put("idCardValidEnd", List.of("失效日期", "有效期限", "有效期限止")); return aliases; @@ -319,7 +323,8 @@ public final class OcrFieldSupport { } private static boolean isDateField(String key) { - return key.endsWith("Date") || key.endsWith("ValidStart") || key.endsWith("ValidEnd"); + // birthday 的语义是日期但拼写不以 Date 结尾,漏了它会把「1990年1月1日」原样下发 + return "birthday".equals(key) || key.endsWith("Date") || key.endsWith("ValidStart") || key.endsWith("ValidEnd"); } private static boolean isNumberField(String key) { diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/PersonCertRoundTripTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/PersonCertRoundTripTest.java index e4639e36..fa1671b7 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/PersonCertRoundTripTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/PersonCertRoundTripTest.java @@ -18,6 +18,7 @@ import org.springblade.transport.service.IDriverService; import org.springblade.transport.service.ITransportCertRecordService; import org.springblade.transport.service.ITransportVehicleService; +import java.time.LocalDate; import java.util.HashMap; import java.util.Map; @@ -239,6 +240,15 @@ class PersonCertRoundTripTest { if (patch.getIdCardNo() != null) { target.setIdCardNo(patch.getIdCardNo()); } + if (patch.getBirthday() != null) { + target.setBirthday(patch.getBirthday()); + } + if (patch.getAddressRegion() != null) { + target.setAddressRegion(patch.getAddressRegion()); + } + if (patch.getAddress() != null) { + target.setAddress(patch.getAddress()); + } if (patch.getIdCardFront() != null) { target.setIdCardFront(patch.getIdCardFront()); } @@ -287,6 +297,9 @@ class PersonCertRoundTripTest { @DisplayName("审核通过:证件内容写回司机档案,档案与生效值一致") void approveWritesCertContentBackToDriver() { PersonCertSubmitRequest request = personCert("张三", "110101199001011234"); + request.setBirthday(LocalDate.of(1990, 1, 1)); + request.setAddressRegion("广西壮族自治区柳州市柳北区"); + request.setAddress("跃进路88号"); request.setHeadPhoto("http://example.com/head.jpg"); request.setDriverClass("A2"); request.setDriverFileNo("450100769875"); @@ -302,6 +315,9 @@ class PersonCertRoundTripTest { // 档案里必须是这次提交的内容:只切指针、不写内容的话, // 认证状态显示「已通过」而档案仍是旧值,管理端与司机端会各看各的 + assertEquals(LocalDate.of(1990, 1, 1), driver.getBirthday()); + assertEquals("广西壮族自治区柳州市柳北区", driver.getAddressRegion()); + assertEquals("跃进路88号", driver.getAddress()); assertEquals("http://example.com/head.jpg", driver.getHeadPhoto()); assertEquals("A2", driver.getDrivingType()); assertEquals("450100769875", driver.getDrivingLicenseNo()); @@ -313,6 +329,25 @@ class PersonCertRoundTripTest { assertEquals("http://example.com/q-back.jpg", driver.getQualificationBack()); } + @Test + @DisplayName("审核通过:住址留空不清空管理端已填的住址") + void approveKeepsAddressWhenSnapshotBlank() { + driver.setAddressRegion("广西壮族自治区柳州市柳北区"); + driver.setAddress("跃进路88号"); + + PersonCertSubmitRequest request = personCert("张三", "110101199001011234"); + request.setAddressRegion(" "); + request.setAddress(""); + Long recordId = driverCertService.submitPersonCert(request); + certAuditService.audit(recordId, true, null); + + // 框架的 not_null 更新策略只跳过 null:写空串会把管理端填过的住址清掉 + assertEquals("广西壮族自治区柳州市柳北区", driver.getAddressRegion(), + "区划是选填项,没选就保持档案原值"); + assertEquals("跃进路88号", driver.getAddress(), + "详细地址是选填项,没填就保持档案原值"); + } + @Test @DisplayName("审核通过:姓名与身份证号跟着认证资料走,档案与生效值不再各说各话") void approveOverwritesIdentity() { diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/support/OcrFieldSupportTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/support/OcrFieldSupportTest.java index f20619d8..25330741 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/support/OcrFieldSupportTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/support/OcrFieldSupportTest.java @@ -124,6 +124,8 @@ class OcrFieldSupportTest { { "words_result": { "姓名": {"words": "黄宇富"}, + "出生": {"words": "1979年11月17日"}, + "住址": {"words": "广西壮族自治区柳州市柳北区跃进路88号"}, "公民身份号码": {"words": "452730197911172318"}, "签发日期": {"words": "2015-03-12"}, "失效日期": {"words": "2035-03-12"} @@ -133,6 +135,8 @@ class OcrFieldSupportTest { Map person = OcrFieldSupport.extract(BaiduOcrType.ID_CARD, "front", idCard); assertEquals("黄宇富", person.get("realName")); assertEquals("452730197911172318", person.get("idCardNo")); + assertEquals("1979-11-17", person.get("birthday"), "「出生」是一串中文日期,要归一成 yyyy-MM-dd 才能填进日期框"); + assertEquals("广西壮族自治区柳州市柳北区跃进路88号", person.get("address")); assertEquals("2015-03-12", person.get("idCardValidStart")); assertEquals("2035-03-12", person.get("idCardValidEnd"));