feat: 实现 OCR 模块和车辆上牌管理功能

- 新增 yudao-module-ocr 模块
  - OCR API 模块:定义 Feign 接口和 DTO
  - OCR Server 模块:实现行驶证识别功能
  - 集成百度 OCR SDK
  - 支持多厂商扩展(百度/腾讯/阿里云)

- 新增车辆上牌管理功能
  - 数据库表:asset_vehicle_registration
  - 完整的 CRUD 接口
  - 行驶证识别接口(集成 OCR)
  - 车辆匹配功能(根据 VIN)
  - 确认上牌功能(更新车辆信息)

- 技术实现
  - 遵循 BPM/System 模块的 RPC API 模式
  - 使用 Feign 实现服务间调用
  - Base64 编码传输图片数据
  - 统一返回格式 CommonResult<T>

- 文档
  - OCR 模块使用文档
  - OCR 部署指南
  - 车辆上牌管理总结
  - API 集成规划和总结
This commit is contained in:
kkfluous
2026-03-12 20:33:21 +08:00
parent 0706b51acd
commit 78a6cde22d
50 changed files with 3886 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>yudao-module-ocr</artifactId>
<groupId>cn.iocoder.cloud</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-ocr-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>OCR 识别 API定义 Feign 接口等</description>
<url>https://github.com/YunaiV/yudao-cloud</url>
<dependencies>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<!-- RPC 远程调用相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-rpc</artifactId>
<scope>provided</scope>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.ocr.api;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseRespDTO;
import cn.iocoder.yudao.module.ocr.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* OCR 识别 API 接口
*
* @author 芋道源码
*/
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - OCR 识别")
public interface OcrApi {
String PREFIX = ApiConstants.PREFIX + "/recognition";
@PostMapping(PREFIX + "/vehicle-license")
@Operation(summary = "识别行驶证(提供给内部模块)")
@Parameter(name = "imageData", description = "图片数据Base64编码", required = true)
@Parameter(name = "provider", description = "OCR厂商可选默认使用配置的默认厂商", example = "baidu")
CommonResult<VehicleLicenseRespDTO> recognizeVehicleLicense(
@RequestParam("imageData") String imageData,
@RequestParam(value = "provider", required = false) String provider);
}

View File

@@ -0,0 +1,86 @@
package cn.iocoder.yudao.module.ocr.api.dto;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDate;
/**
* 行驶证识别结果 DTO
*
* @author 芋道源码
*/
@Data
public class VehicleLicenseRespDTO implements Serializable {
/**
* 车辆识别代号VIN
*/
private String vin;
/**
* 号牌号码
*/
private String plateNo;
/**
* 品牌型号
*/
private String brand;
/**
* 车辆类型
*/
private String vehicleType;
/**
* 所有人
*/
private String owner;
/**
* 使用性质
*/
private String useCharacter;
/**
* 发动机号码
*/
private String engineNo;
/**
* 注册日期
*/
private LocalDate registerDate;
/**
* 发证日期
*/
private LocalDate issueDate;
/**
* 检验记录
*/
private String inspectionRecord;
/**
* 强制报废期止
*/
private LocalDate scrapDate;
/**
* 整备质量kg
*/
private String curbWeight;
/**
* 总质量kg
*/
private String totalMass;
/**
* 核定载人数
*/
private String approvedPassengerCapacity;
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.ocr.enums;
import cn.iocoder.yudao.framework.common.enums.RpcConstants;
/**
* API 相关的枚举
*
* @author 芋道源码
*/
public class ApiConstants {
/**
* 服务名
*
* 注意,需要保证和 spring.application.name 保持一致
*/
public static final String NAME = "ocr-server";
public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/ocr";
public static final String VERSION = "1.0.0";
}

View File

@@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.ocr.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* OCR 错误码枚举类
*
* ocr 系统,使用 1-009-000-000 段
*/
public interface ErrorCodeConstants {
// ========== OCR 识别 1-009-001-000 ==========
ErrorCode OCR_PROVIDER_NOT_SUPPORTED = new ErrorCode(1_009_001_000, "不支持的 OCR 厂商");
ErrorCode OCR_SCENE_NOT_SUPPORTED = new ErrorCode(1_009_001_001, "不支持的识别场景");
ErrorCode OCR_IMAGE_INVALID = new ErrorCode(1_009_001_002, "图片格式不正确或已损坏");
ErrorCode OCR_IMAGE_TOO_LARGE = new ErrorCode(1_009_001_003, "图片大小超过限制");
ErrorCode OCR_RECOGNIZE_FAILED = new ErrorCode(1_009_001_004, "识别失败");
ErrorCode OCR_CLIENT_CONFIG_INVALID = new ErrorCode(1_009_001_005, "OCR 客户端配置无效");
}

View File

@@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.ocr.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* OCR 厂商枚举
*/
@Getter
@AllArgsConstructor
public enum OcrProviderEnum {
BAIDU("baidu", "百度 OCR"),
TENCENT("tencent", "腾讯 OCR"),
ALIYUN("aliyun", "阿里云 OCR"),
;
/**
* 厂商编码
*/
private final String code;
/**
* 厂商名称
*/
private final String name;
}

View File

@@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.ocr.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* OCR 识别场景枚举
*/
@Getter
@AllArgsConstructor
public enum OcrSceneEnum {
VEHICLE_LICENSE("vehicle_license", "行驶证识别"),
DRIVER_LICENSE("driver_license", "驾驶证识别"),
ID_CARD("id_card", "身份证识别"),
BUSINESS_LICENSE("business_license", "营业执照识别"),
;
/**
* 场景编码
*/
private final String code;
/**
* 场景名称
*/
private final String name;
}