From aca05abd73fecea44b44cc97f996fc4ece053a5b Mon Sep 17 00:00:00 2001 From: zhonghua1 Date: Sun, 11 Jan 2026 10:06:00 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E7=94=A8ai=E6=A8=A1=E5=9E=8B=E5=88=86?= =?UTF-8?q?=E6=9E=90=E5=AE=B6=E5=B1=85=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HikariCP连接池问题分析.md | 1 + .../controller/AudioManagementController.java | 44 ++- .../AudioTextAnalysisFurnitureController.java | 46 +-- .../service/IAudioTextAnalysisLlmService.java | 23 ++ .../impl/AudioTextAnalysisLlmServiceImpl.java | 367 ++++++++++++++++++ 5 files changed, 438 insertions(+), 43 deletions(-) diff --git a/HikariCP连接池问题分析.md b/HikariCP连接池问题分析.md index aac6d95..19b0347 100644 --- a/HikariCP连接池问题分析.md +++ b/HikariCP连接池问题分析.md @@ -139,5 +139,6 @@ hikari: + diff --git a/src/main/java/com/rj/controller/AudioManagementController.java b/src/main/java/com/rj/controller/AudioManagementController.java index bf28e1b..a02a790 100644 --- a/src/main/java/com/rj/controller/AudioManagementController.java +++ b/src/main/java/com/rj/controller/AudioManagementController.java @@ -7,6 +7,7 @@ import com.rj.common.AudioManagementConstants; import com.rj.common.DataEnrichmentUtil; import com.rj.entity.AudioManagement; import com.rj.entity.AudioManagementSegments; +import com.rj.entity.AudioTextAnalysisFurniture; import com.rj.entity.CustomerManagement; import com.rj.service.*; import com.rj.dto.AsrRequest; @@ -44,7 +45,7 @@ import java.util.UUID; public class AudioManagementController { // 场景常量,避免在解析逻辑中硬编码字符串 - private static final String SCENARIO_FURNITURE_SALE = "FURNITURE_SALE"; + private static final String SCENARIO_FURNITURE_SALE = "FURNITURE"; private static final String SCENARIO_MEETING_SUMMARY = "MEETING_SUMMARY"; private static final String SCENARIO_CAR_SALE = "CAR_SALE"; private static final String SCENARIO_SPEAKING_TRAINING= "SPEAKING_TRAINING"; //租赁模式 @@ -637,6 +638,7 @@ public class AudioManagementController { @Parameter(description = "录音信息", required = true) @RequestBody AudioManagement audioManagement) { Map result = new HashMap<>(); + boolean success = true; try { if (audioManagement.getId() == null || audioManagement.getId().trim().isEmpty()) { result.put("success", false); @@ -651,6 +653,14 @@ public class AudioManagementController { result.put("message", "记录不存在"); return ResponseEntity.badRequest().body(result); } + // 2. 检查summary字段,如果已存在总结内容,直接返回提示,不进行AI分析 + String summary = audioManagement.getSummary(); + if (summary != null && !summary.trim().isEmpty()) { + result.put("success", true); + result.put("message", "AI分析已完成"); + result.put("data", audioManagement); + return ResponseEntity.ok(result); + } // 3. 获取录音文本;如主表为空,则从分段表拼接 String recordingText = audioManagementFromDB.getRecordingText(); if (recordingText == null || recordingText.trim().isEmpty()) { @@ -688,23 +698,35 @@ public class AudioManagementController { // 4. 根据场景动态选择业务场景类型,调用业务层通用服务生成总结 AudioAnalysisSceneType sceneType = resolveSceneType(audioManagementFromDB.getScenario()); - String rawContent = audioTextAnalysisLlmService.generateSummaryByLLM( + if (recordingText == null || recordingText.trim().isEmpty()) { + result.put("success", false); + result.put("message", "录音文本为空"); + return ResponseEntity.badRequest().body(result); + } + + // 4. 通过业务层通用服务调用大模型生成总结并保存数据 + AudioTextAnalysisFurniture furniture = audioTextAnalysisLlmService.generateSummaryAndSave( sceneType, - recordingText + recordingText, + audioManagement.getId(), + audioManagement.getSalesName(), + audioManagement.getSalesPhone(), + audioManagement.getCustomerName(), + audioManagement.getCustomerPhone() ); - - - boolean success = true; - if (success) { + log.info("llm return furniture Analysis : ",furniture.toString() ); + if (recordingText == null || recordingText.trim().isEmpty()) { + result.put("success", false); + result.put("message", "录音文本为空"); + return ResponseEntity.badRequest().body(result); + } else { result.put("success", true); result.put("message", "录音finishServiceById更新成功"); result.put("data", audioManagement); return ResponseEntity.ok(result); - } else { - result.put("success", false); - result.put("message", "录音finishServiceById更新失败"); - return ResponseEntity.badRequest().body(result); } + + } catch (Exception e) { result.put("success", false); result.put("message", "更新异常:" + e.getMessage()); diff --git a/src/main/java/com/rj/controller/AudioTextAnalysisFurnitureController.java b/src/main/java/com/rj/controller/AudioTextAnalysisFurnitureController.java index e69c472..ad9c8cd 100644 --- a/src/main/java/com/rj/controller/AudioTextAnalysisFurnitureController.java +++ b/src/main/java/com/rj/controller/AudioTextAnalysisFurnitureController.java @@ -237,6 +237,14 @@ public class AudioTextAnalysisFurnitureController { result.put("message", "记录不存在"); return ResponseEntity.badRequest().body(result); } + // 2. 检查summary字段,如果已存在总结内容,直接返回提示,不进行AI分析 + String summary = audioManagement.getSummary(); + if (summary != null && !summary.trim().isEmpty()) { + result.put("success", true); + result.put("message", "AI分析已完成"); + result.put("data", audioManagement); + return ResponseEntity.ok(result); + } // 3. 获取录音文本 String recordingText = audioManagement.getRecordingText(); if (recordingText == null || recordingText.trim().isEmpty()) { @@ -244,16 +252,10 @@ public class AudioTextAnalysisFurnitureController { result.put("message", "录音文本为空"); return ResponseEntity.badRequest().body(result); } - AudioTextAnalysisFurniture furniture = new AudioTextAnalysisFurniture(); - furniture.setRecordingText(recordingText); - // 4. 通过业务层通用服务调用大模型生成总结,然后解析结构化结果 - String rawContent = audioTextAnalysisLlmService.generateSummaryByLLM( - AudioAnalysisSceneType.SCENARIO_MEETING_SUMMARY, - furniture.getRecordingText() - ); - applyStructuredResult( - furniture, - rawContent, + // 4. 通过业务层通用服务调用大模型生成总结并保存数据 + AudioTextAnalysisFurniture furniture = audioTextAnalysisLlmService.generateSummaryAndSave( + AudioAnalysisSceneType.SCENARIO_FURNITURE_SALE, + recordingText, id, audioManagement.getSalesName(), audioManagement.getSalesPhone(), @@ -261,34 +263,14 @@ public class AudioTextAnalysisFurnitureController { audioManagement.getCustomerPhone() ); - - audioManagement = new AudioManagement(); - audioManagement.setSummary(furniture.getSummarySentence()); - audioManagement.setId(id); - audioManagementService.updateById(audioManagement); - - - // 5. 保存总结到数据库 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(AudioTextAnalysisFurniture::getParentId, id); - AudioTextAnalysisFurniture one = furnitureService.getOne(wrapper); - if (one != null) { - furniture.setId(one.getId()); - } - - furniture.setUpdatedAt(LocalDateTime.now()); - furniture.setParentId( id); - furniture.setRecordingText(null); - boolean updateSuccess = furnitureService.saveOrUpdate(furniture); - - if (updateSuccess) { + if (furniture != null) { result.put("success", true); result.put("message", "生成总结成功"); result.put("data", furniture); return ResponseEntity.ok(result); } else { result.put("success", false); - result.put("message", "保存总结失败"); + result.put("message", "生成总结并保存失败"); return ResponseEntity.badRequest().body(result); } diff --git a/src/main/java/com/rj/service/IAudioTextAnalysisLlmService.java b/src/main/java/com/rj/service/IAudioTextAnalysisLlmService.java index 3f1fdeb..5724e31 100644 --- a/src/main/java/com/rj/service/IAudioTextAnalysisLlmService.java +++ b/src/main/java/com/rj/service/IAudioTextAnalysisLlmService.java @@ -1,6 +1,7 @@ package com.rj.service; import com.rj.common.AudioAnalysisSceneType; +import com.rj.entity.AudioTextAnalysisFurniture; /** * 音频文本分析 - 大模型通用服务 @@ -19,6 +20,28 @@ public interface IAudioTextAnalysisLlmService { * @return 大模型返回的原始内容(一般是 JSON 字符串或结构化文本) */ String generateSummaryByLLM(AudioAnalysisSceneType sceneType, String recordingText); + + /** + * 处理完整的业务逻辑:调用大模型生成总结,解析JSON,保存数据 + * 此方法用于家具场景的完整业务处理 + * + * @param sceneType 业务场景类型 + * @param recordingText 录音转写文本 + * @param parentId 父ID(AudioManagement的ID) + * @param ownerName 所属人姓名 + * @param ownerPhone 所属人电话 + * @param customerName 客户姓名 + * @param customerPhone 客户电话 + * @return 保存后的AudioTextAnalysisFurniture对象,如果处理失败返回null + */ + AudioTextAnalysisFurniture generateSummaryAndSave( + AudioAnalysisSceneType sceneType, + String recordingText, + String parentId, + String ownerName, + String ownerPhone, + String customerName, + String customerPhone); } diff --git a/src/main/java/com/rj/service/impl/AudioTextAnalysisLlmServiceImpl.java b/src/main/java/com/rj/service/impl/AudioTextAnalysisLlmServiceImpl.java index e117328..40379d5 100644 --- a/src/main/java/com/rj/service/impl/AudioTextAnalysisLlmServiceImpl.java +++ b/src/main/java/com/rj/service/impl/AudioTextAnalysisLlmServiceImpl.java @@ -7,16 +7,31 @@ import com.alibaba.dashscope.common.Message; import com.alibaba.dashscope.common.Role; import com.alibaba.dashscope.exception.InputRequiredException; import com.alibaba.dashscope.exception.NoApiKeyException; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.rj.common.AudioAnalysisSceneType; +import com.rj.entity.AudioManagement; +import com.rj.entity.AudioTextAnalysisFurniture; +import com.rj.entity.AudioTextAnalysisSop; +import com.rj.entity.TodoItem; +import com.rj.service.IAudioManagementService; +import com.rj.service.IAudioTextAnalysisFurnitureService; import com.rj.service.IAudioTextAnalysisLlmService; +import com.rj.service.IAudioTextAnalysisSopService; +import com.rj.service.ITodoItemService; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.Map; import java.util.Scanner; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; /** @@ -29,6 +44,21 @@ public class AudioTextAnalysisLlmServiceImpl implements IAudioTextAnalysisLlmSer private static final Map SYSTEM_PROMPT_CACHE = new ConcurrentHashMap<>(); private static final Map USER_PROMPT_CACHE = new ConcurrentHashMap<>(); + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private IAudioTextAnalysisFurnitureService furnitureService; + + @Autowired + private IAudioManagementService audioManagementService; + + @Autowired + private ITodoItemService todoItemService; + + @Autowired + private IAudioTextAnalysisSopService sopService; + @Override public String generateSummaryByLLM(AudioAnalysisSceneType sceneType, String recordingText) { long startTime = System.currentTimeMillis(); @@ -129,6 +159,343 @@ public class AudioTextAnalysisLlmServiceImpl implements IAudioTextAnalysisLlmSer return null; } } + + /** + * 处理完整的业务逻辑:调用大模型生成总结,解析JSON,保存数据 + * 此方法用于家具场景的完整业务处理 + * + * @param sceneType 业务场景类型 + * @param recordingText 录音转写文本 + * @param parentId 父ID(AudioManagement的ID) + * @param ownerName 所属人姓名 + * @param ownerPhone 所属人电话 + * @param customerName 客户姓名 + * @param customerPhone 客户电话 + * @return 保存后的AudioTextAnalysisFurniture对象,如果处理失败返回null + */ + @Override + public AudioTextAnalysisFurniture generateSummaryAndSave( + AudioAnalysisSceneType sceneType, + String recordingText, + String parentId, + String ownerName, + String ownerPhone, + String customerName, + String customerPhone) { + try { + // 1. 调用大模型生成总结 + String rawContent = generateSummaryByLLM(sceneType, recordingText); + if (rawContent == null || rawContent.trim().isEmpty()) { + log.warn("大模型返回内容为空"); + return null; + } + + // 2. 创建AudioTextAnalysisFurniture对象 + AudioTextAnalysisFurniture furniture = new AudioTextAnalysisFurniture(); + furniture.setRecordingText(recordingText); + + // 3. 解析JSON并填充对象 + applyStructuredResult(furniture, rawContent, parentId, ownerName, ownerPhone, customerName, customerPhone); + + // 4. 更新AudioManagement的summary字段 + AudioManagement audioManagement = new AudioManagement(); + audioManagement.setId(parentId); + audioManagement.setSummary(furniture.getSummarySentence()); + audioManagementService.updateById(audioManagement); + + // 5. 保存或更新AudioTextAnalysisFurniture记录 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(AudioTextAnalysisFurniture::getParentId, parentId); + AudioTextAnalysisFurniture existing = furnitureService.getOne(wrapper); + LocalDateTime now = LocalDateTime.now(); + if (existing != null) { + furniture.setId(existing.getId()); + // 更新记录:只设置更新时间,不修改创建时间 + furniture.setUpdatedAt(now); + } else { + // 新增记录:需要设置创建时间和更新时间 + furniture.setCreatedAt(now); + furniture.setUpdatedAt(now); + } + + furniture.setParentId(parentId); + furniture.setRecordingText(null); // 保存时清除recordingText + furniture.setOwnerPhone(ownerPhone); + furniture.setCustomerPhone(customerPhone); + boolean success = furnitureService.saveOrUpdate(furniture); + if (success) { + log.info("保存AudioTextAnalysisFurniture成功,ID: {}, parentId: {}", furniture.getId(), parentId); + return furniture; + } else { + log.warn("保存AudioTextAnalysisFurniture失败,parentId: {}", parentId); + return null; + } + } catch (Exception e) { + log.error("生成总结并保存失败,parentId: {}", parentId, e); + throw new RuntimeException("生成总结并保存失败: " + e.getMessage(), e); + } + } + + /** + * 解析大模型返回的JSON结果并填充到AudioTextAnalysisFurniture对象 + * + * @param furniture 家具意向分析对象 + * @param rawContent 大模型返回的原始内容 + * @param parentId 父ID + * @param ownerName 所属人姓名 + * @param ownerPhone 所属人电话 + * @param customerName 客户姓名 + * @param customerPhone 客户电话 + */ + private void applyStructuredResult( + AudioTextAnalysisFurniture furniture, + String rawContent, + String parentId, + String ownerName, + String ownerPhone, + String customerName, + String customerPhone) { + String normalized = normalizeJson(rawContent); + try { + JsonNode root = objectMapper.readTree(normalized); + + // 基础字段 + furniture.setCustomerType(textValue(root, "customer_type")); + furniture.setFamilyStructure(textValue(root, "family_structure")); + furniture.setIntentionProducts(textValue(root, "intention_products")); + furniture.setSummarySentence(textValue(root, "summary")); + furniture.setDecorationStyle(textValue(root, "decoration_style")); + + // 产品维度字段,每个都是JSON对象,需要转换为JSON字符串 + furniture.setSofa(jsonObjectToString(root, "sofa")); + furniture.setTeaTable(jsonObjectToString(root, "tea_table")); + furniture.setDiningTable(jsonObjectToString(root, "dining_table")); + furniture.setStudyDesk(jsonObjectToString(root, "study_desk")); + furniture.setTvCabinet(jsonObjectToString(root, "tv_cabinet")); + furniture.setCabinet(jsonObjectToString(root, "cabinet")); + furniture.setWineCabinet(jsonObjectToString(root, "wine_cabinet")); + furniture.setMasterBedroomCabinet(jsonObjectToString(root, "master_bedroom_cabinet")); + furniture.setSecondaryBedroomCabinet(jsonObjectToString(root, "secondary_bedroom_cabinet")); + furniture.setShoeCabinet(jsonObjectToString(root, "shoe_cabinet")); + furniture.setBedAndMattress(jsonObjectToString(root, "bed_and_mattress")); + furniture.setSummary1(jsonObjectToString(root, "summary1")); + furniture.setSummary2(jsonObjectToString(root, "summary2")); + furniture.setSummary3(jsonObjectToString(root, "summary3")); + + // 解析并保存待办事项 + saveTodoItems(root, parentId, ownerName, ownerPhone); + + // 解析并保存SOP评分信息 + saveSopInfo(root, parentId, ownerName, ownerPhone, customerName, customerPhone); + } catch (JsonProcessingException e) { + log.warn("解析大模型返回JSON失败,使用原始内容作为总结: {}", e.getMessage()); + furniture.setSummarySentence(rawContent); + } + } + + /** + * 规范化JSON字符串(去除markdown代码块标记等) + */ + private String normalizeJson(String content) { + if (content == null) { + return ""; + } + String trimmed = content.trim(); + if (trimmed.startsWith("```")) { + int firstLineBreak = trimmed.indexOf('\n'); + int lastFence = trimmed.lastIndexOf("```"); + if (firstLineBreak >= 0 && lastFence > firstLineBreak) { + trimmed = trimmed.substring(firstLineBreak + 1, lastFence).trim(); + } + } + return trimmed; + } + + /** + * 从JSON节点中获取文本值 + */ + private String textValue(JsonNode root, String field) { + JsonNode node = root.get(field); + return node == null || node.isNull() ? null : node.asText(); + } + + /** + * 将JSON对象节点转换为JSON字符串 + */ + private String jsonObjectToString(JsonNode root, String field) { + JsonNode node = root.get(field); + if (node == null || node.isNull()) { + return null; + } + try { + if (node.isObject()) { + return objectMapper.writeValueAsString(node); + } else if (node.isTextual()) { + return node.asText(); + } else { + return objectMapper.writeValueAsString(node); + } + } catch (JsonProcessingException e) { + log.warn("转换JSON对象失败,字段: {}, 错误: {}", field, e.getMessage()); + return node.isTextual() ? node.asText() : node.toString(); + } + } + + /** + * 解析并保存待办事项 + */ + private void saveTodoItems(JsonNode root, String parentId, String ownerName, String ownerPhone) { + try { + JsonNode todoItemsNode = root.get("todo_item"); + if (todoItemsNode == null || !todoItemsNode.isArray()) { + log.info("未找到待办事项数组或格式不正确"); + return; + } + + LocalDateTime now = LocalDateTime.now(); + int savedCount = 0; + + for (JsonNode todoItemNode : todoItemsNode) { + if (!todoItemNode.isObject()) { + log.warn("待办事项项不是JSON对象,跳过"); + continue; + } + + String todoTitle = textValue(todoItemNode, "todo_title"); + String todoDetail = textValue(todoItemNode, "todo_detail"); + + // 如果标题和详情都为空,跳过 + if ((todoTitle == null || todoTitle.trim().isEmpty()) && + (todoDetail == null || todoDetail.trim().isEmpty())) { + log.warn("待办事项标题和详情都为空,跳过"); + continue; + } + + TodoItem todoItem = new TodoItem(); + todoItem.setId(UUID.randomUUID().toString()); + todoItem.setParentId(parentId); + todoItem.setTodoTitle(todoTitle != null ? todoTitle.trim() : ""); + todoItem.setTodoDetail(todoDetail != null ? todoDetail.trim() : ""); + todoItem.setOwnerName(ownerName); + todoItem.setOwnerPhone(ownerPhone); + todoItem.setStatus("待处理"); + todoItem.setCreateTime(now); + todoItem.setUpdateTime(now); + todoItem.setPendingDate(now.plusDays(3)); + + boolean success = todoItemService.save(todoItem); + if (success) { + savedCount++; + log.info("保存待办事项成功,ID: {}, 标题: {}", todoItem.getId(), todoItem.getTodoTitle()); + } else { + log.warn("保存待办事项失败,标题: {}", todoItem.getTodoTitle()); + } + } + + log.info("待办事项保存完成,共保存 {} 条", savedCount); + } catch (Exception e) { + log.error("保存待办事项时发生异常", e); + // 不抛出异常,避免影响主流程 + } + } + + /** + * 解析并保存SOP评分信息 + */ + private void saveSopInfo( + JsonNode root, + String parentId, + String ownerName, + String ownerPhone, + String customerName, + String customerPhone) { + try { + JsonNode comprehensiveScoreNode = root.get("comprehensive_score"); + if (comprehensiveScoreNode == null) { + log.info("未找到SOP评分信息,跳过保存"); + return; + } + + AudioTextAnalysisSop sop = new AudioTextAnalysisSop(); + sop.setId(UUID.randomUUID().toString()); + sop.setParentId(parentId); + sop.setOwnerName(ownerName); + sop.setOwnerPhone(ownerPhone); + sop.setCustomerName(customerName); + sop.setCustomerPhone(customerPhone); + sop.setIndustryType("furniture"); + + // 解析SOP评分字段 + sop.setComprehensiveScore(intValue(root, "comprehensive_score")); + sop.setScoreSummaryReason(textValue(root, "score_summary_reason")); + sop.setGreetingIceBreaking(intValue(root, "greeting_ice_breaking")); + sop.setBrandIntroduction(intValue(root, "brand_introduction")); + sop.setGoldenThreeQuestions(intValue(root, "golden_three_questions")); + sop.setNeedsGuidance(intValue(root, "needs_guidance")); + sop.setServiceProgression(intValue(root, "service_progression")); + sop.setReassuranceHandbook(intValue(root, "reassurance_handbook")); + sop.setThreeLevelPricing(intValue(root, "three_level_pricing")); + sop.setObjectionHandling(intValue(root, "objection_handling")); + sop.setActivityImplantation(intValue(root, "activity_implantation")); + sop.setClosingCooperation(intValue(root, "closing_cooperation")); + sop.setProactiveWechatAdd(intValue(root, "proactive_wechat_add")); + sop.setPoliteFarewell(intValue(root, "polite_farewell")); + + // 设置时间 + LocalDateTime now = LocalDateTime.now(); + sop.setCreatedAt(now); + sop.setUpdatedAt(now); + + // 检查是否已存在相同parentId的记录,如果存在则更新,否则新增 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(AudioTextAnalysisSop::getParentId, parentId); + AudioTextAnalysisSop existingSop = sopService.getOne(wrapper); + if (existingSop != null) { + sop.setId(existingSop.getId()); + boolean success = sopService.updateById(sop); + if (success) { + log.info("更新SOP评分信息成功,ID: {}, parentId: {}", sop.getId(), parentId); + } else { + log.warn("更新SOP评分信息失败,parentId: {}", parentId); + } + } else { + boolean success = sopService.save(sop); + if (success) { + log.info("保存SOP评分信息成功,ID: {}, parentId: {}", sop.getId(), parentId); + } else { + log.warn("保存SOP评分信息失败,parentId: {}", parentId); + } + } + } catch (Exception e) { + log.error("保存SOP评分信息时发生异常", e); + // 不抛出异常,避免影响主流程 + } + } + + /** + * 从JSON节点中获取整数值 + */ + private Integer intValue(JsonNode root, String field) { + JsonNode node = root.get(field); + if (node == null || node.isNull()) { + return null; + } + if (node.isInt()) { + return node.asInt(); + } else if (node.isTextual()) { + try { + String text = node.asText(); + if (text == null || text.trim().isEmpty()) { + return null; + } + return Integer.parseInt(text.trim()); + } catch (NumberFormatException e) { + log.warn("无法将字段 {} 的值 {} 转换为整数", field, node.asText()); + return null; + } + } + return null; + } }