diff --git a/api-web/api-interface/src/main/java/com/heyu/api/controller/doc/DocClassifyController.java b/api-web/api-interface/src/main/java/com/heyu/api/controller/doc/DocClassifyController.java index 56a9af7..c75ff0c 100644 --- a/api-web/api-interface/src/main/java/com/heyu/api/controller/doc/DocClassifyController.java +++ b/api-web/api-interface/src/main/java/com/heyu/api/controller/doc/DocClassifyController.java @@ -13,6 +13,7 @@ import com.heyu.api.data.utils.R; import com.heyu.api.data.utils.StringUtils; import com.heyu.api.request.doc.DocClassifyRequest; import com.heyu.api.resp.doc.DocClassifyItemResp; +import com.heyu.api.resp.doc.DocClassifyLocationResp; import com.heyu.api.resp.doc.DocClassifyResp; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; @@ -195,7 +196,7 @@ public class DocClassifyController extends AbstractRecognizeController { "解析状态=结果集为空" ); } - if (data == null || data.getItems() == null || data.getItems().isEmpty()) { + if (data == null || data.getWordsResult() == null || data.getWordsResult().isEmpty()) { log.info("文档分类:平台有返回,但分类结果列表为空(可能图片不包含可识别主体)。{}。客户传的:{}。平台回执:{}", ctx.imageInput.getType().getDesc(), ctx.inputLog, buildPlatformReceiptSummary(platformResult)); @@ -215,7 +216,7 @@ public class DocClassifyController extends AbstractRecognizeController { "字段映射为空", "平台回执包含分类条目,但类别、置信度、位置等结构化字段均未命中", "请确认上传图片清晰且包含可识别的文档、卡证或票据主体", - "分类条目数=" + data.getItems().size() + ",有效字段数=0" + "分类条目数=" + data.getWordsResult().size() + ",有效字段数=0" ); } return null; @@ -224,7 +225,7 @@ public class DocClassifyController extends AbstractRecognizeController { private void logRecognizeResult(RecognizeContext ctx, Map platformResult, DocClassifyResp data, String hint, long start) { long cost = System.currentTimeMillis() - start; - int itemCount = data != null && data.getItems() != null ? data.getItems().size() : 0; + int itemCount = data != null && data.getWordsResult() != null ? data.getWordsResult().size() : 0; int totalFields = countTotalItemFields(data); if (StringUtils.isNotBlank(hint)) { log.info("文档分类:处理结束(接口仍返回成功,但带了提示信息)。耗时 {} ms,分类出 {} 个主体、共 {} 个字段。" @@ -290,12 +291,15 @@ public class DocClassifyController extends AbstractRecognizeController { @SuppressWarnings("unchecked") private DocClassifyResp buildResp(Map platformResult) { DocClassifyResp resp = new DocClassifyResp(); - Object wordsResult = platformResult.get("words_result"); - Object wordsResultNum = platformResult.get("words_result_num"); - resp.setCount(wordsResultNum != null ? String.valueOf(wordsResultNum) : "0"); + // 一级字段:log_id + Object logId = platformResult.get("log_id"); + resp.setLogId(logId != null ? String.valueOf(logId) : null); + + // 一级字段:words_result + Object wordsResult = platformResult.get("words_result"); if (!(wordsResult instanceof List)) { - resp.setItems(Collections.emptyList()); + resp.setWordsResult(Collections.emptyList()); return resp; } List> resultList = (List>) wordsResult; @@ -303,26 +307,32 @@ public class DocClassifyController extends AbstractRecognizeController { for (Map item : resultList) { items.add(buildItemResp(item)); } - resp.setItems(items); + resp.setWordsResult(items); return resp; } @SuppressWarnings("unchecked") private DocClassifyItemResp buildItemResp(Map item) { DocClassifyItemResp resp = new DocClassifyItemResp(); + + // 二级字段:type Object type = item.get("type"); resp.setType(type != null ? String.valueOf(type) : null); - // 注意:百度 API 原始字段名为 "probablity"(拼写错误),此处与之保持一致 + + // 二级字段:probability(注意:百度 API 原始字段名为 "probablity",拼写错误,此处与之保持一致) Object prob = item.get("probablity"); resp.setProbability(prob != null ? String.valueOf(prob) : null); + // 二级字段:location(嵌套对象) Object location = item.get("location"); if (location instanceof Map) { Map loc = (Map) location; - resp.setTop(stringOrNull(loc.get("top"))); - resp.setLeft(stringOrNull(loc.get("left"))); - resp.setWidth(stringOrNull(loc.get("width"))); - resp.setHeight(stringOrNull(loc.get("height"))); + DocClassifyLocationResp locationResp = new DocClassifyLocationResp(); + locationResp.setLeft(stringOrNull(loc.get("left"))); + locationResp.setTop(stringOrNull(loc.get("top"))); + locationResp.setWidth(stringOrNull(loc.get("width"))); + locationResp.setHeight(stringOrNull(loc.get("height"))); + resp.setLocation(locationResp); } return resp; } @@ -353,11 +363,11 @@ public class DocClassifyController extends AbstractRecognizeController { * 统计所有分类条目的非空字段总数(使用父类反射工具)。 */ private int countTotalItemFields(DocClassifyResp data) { - if (data == null || data.getItems() == null) { + if (data == null || data.getWordsResult() == null) { return 0; } int total = 0; - for (DocClassifyItemResp item : data.getItems()) { + for (DocClassifyItemResp item : data.getWordsResult()) { total += countNonBlankStringFields(item); } return total; @@ -370,10 +380,10 @@ public class DocClassifyController extends AbstractRecognizeController { * 改为遍历每条 ItemResp 做反射判断。

*/ private boolean isAllItemsFieldsBlank(DocClassifyResp data) { - if (data == null || data.getItems() == null || data.getItems().isEmpty()) { + if (data == null || data.getWordsResult() == null || data.getWordsResult().isEmpty()) { return true; } - for (DocClassifyItemResp item : data.getItems()) { + for (DocClassifyItemResp item : data.getWordsResult()) { if (!isAllStringFieldsBlank(item)) { return false; } diff --git a/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyItemResp.java b/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyItemResp.java index 04e7f7b..dd3f9c0 100644 --- a/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyItemResp.java +++ b/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyItemResp.java @@ -3,10 +3,14 @@ package com.heyu.api.resp.doc; import lombok.Data; /** - * 文档分类检测 — 单个分类结果项。 + * 文档分类检测 — 单个分类结果项(words_result 数组元素)。 *

- * 所有字段均为 String 类型,保证反射统计工具覆盖。 - * 字段与百度 doc_classify 接口返回的 words_result 数组元素一一对应。 + * 二级字段: + *

    + *
  • type — 类别信息
  • + *
  • probability — 分类置信度
  • + *
  • location — 位置数组(左上角为坐标0点)
  • + *
*

* * @author zhengli @@ -23,38 +27,16 @@ public class DocClassifyItemResp { private String type; /** - * 分类置信度(0~1 之间的小数,字符串形式)。 - * 对应百度字段:probablity(float) + * 分类置信度(0~1 之间的小数)。 + * 对应百度字段:probability(float) * 示例:"0.9999860525" */ private String probability; /** - * 位置信息 — 表示定位位置的长方形左上顶点的垂直坐标(像素)。 - * 对应百度字段:location.top(uint32) - * 示例:"1684" + * 位置信息(左上角为坐标0点)。 + * 对应百度字段:location(object) */ - private String top; - - /** - * 位置信息 — 表示定位位置的长方形左上顶点的水平坐标(像素)。 - * 对应百度字段:location.left(uint32) - * 示例:"300" - */ - private String left; - - /** - * 位置信息 — 表示定位位置的长方形的宽度(像素)。 - * 对应百度字段:location.width(uint32) - * 示例:"2710" - */ - private String width; - - /** - * 位置信息 — 表示定位位置的长方形的高度(像素)。 - * 对应百度字段:location.height(uint32) - * 示例:"1712" - */ - private String height; + private DocClassifyLocationResp location; } diff --git a/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyLocationResp.java b/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyLocationResp.java new file mode 100644 index 0000000..02e3fb1 --- /dev/null +++ b/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyLocationResp.java @@ -0,0 +1,41 @@ +package com.heyu.api.resp.doc; + +import lombok.Data; + +/** + * 文档分类检测 — 位置信息(location 子对象)。 + *

+ * 表示定位位置的长方形,左上角为坐标0点。 + *

+ * + * @author zhengli + * @since 20260609_zl + */ +@Data +public class DocClassifyLocationResp { + + /** + * 表示定位位置的长方形左上顶点的水平坐标(像素)。 + * 对应百度字段:location.left(uint32) + */ + private String left; + + /** + * 表示定位位置的长方形左上顶点的垂直坐标(像素)。 + * 对应百度字段:location.top(uint32) + */ + private String top; + + /** + * 表示定位位置的长方形的宽度(像素)。 + * 对应百度字段:location.width(uint32) + */ + private String width; + + /** + * 表示定位位置的长方形的高度(像素)。 + * 对应百度字段:location.height(uint32) + */ + private String height; + +} diff --git a/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyResp.java b/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyResp.java index 863251c..389bead 100644 --- a/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyResp.java +++ b/api-web/api-interface/src/main/java/com/heyu/api/resp/doc/DocClassifyResp.java @@ -5,11 +5,13 @@ import lombok.Data; import java.util.List; /** - * 文档分类检测响应。 + * 文档分类检测响应,对齐百度官方接口返回结构。 *

- * 对图片中的文档、卡证、票据等含文字的主体进行检测和分类, - * 返回每个主体的类别、置信度和位置信息。 - * 如图片中无文字内容,items 为空列表。 + * 一级字段: + *

    + *
  • logId — 唯一的日志id,用于问题定位
  • + *
  • wordsResult — 检测和分类结果数组,如图片中无文字内容,则此数组为空
  • + *
*

* * @author zhengli @@ -19,15 +21,15 @@ import java.util.List; public class DocClassifyResp { /** - * 分类结果列表;图片中无文字内容时为空列表。 - * 示例:[{type="卡证_银行卡", probability="0.9999860525", top="1684", left="300", width="2710", height="1712"}] + * 唯一的日志id,用于问题定位。 + * 对应百度字段:log_id(uint64) */ - private List items; + private String logId; /** - * 检测到的主体数量。 - * 示例:"3" + * 检测和分类结果数组;如图片中无文字内容,则此数组为空。 + * 对应百度字段:words_result(array) */ - private String count; + private List wordsResult; }