调用ai模型分析家居场景
This commit is contained in:
@@ -139,5 +139,6 @@ hikari:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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<String, Object> 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());
|
||||
|
||||
@@ -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<AudioTextAnalysisFurniture> 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<String, String> SYSTEM_PROMPT_CACHE = new ConcurrentHashMap<>();
|
||||
private static final Map<String, String> 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<AudioTextAnalysisFurniture> 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<AudioTextAnalysisSop> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user