diff --git a/src/main/java/com/rj/common/PasswordUtil.java b/src/main/java/com/rj/common/PasswordUtil.java index f170460..bc82404 100644 --- a/src/main/java/com/rj/common/PasswordUtil.java +++ b/src/main/java/com/rj/common/PasswordUtil.java @@ -124,5 +124,6 @@ public class PasswordUtil { + diff --git a/src/main/java/com/rj/common/ServiceManager.java b/src/main/java/com/rj/common/ServiceManager.java index e11d820..c2c418b 100644 --- a/src/main/java/com/rj/common/ServiceManager.java +++ b/src/main/java/com/rj/common/ServiceManager.java @@ -108,5 +108,6 @@ public class ServiceManager { + diff --git a/src/main/java/com/rj/config/AliyunConfig.java b/src/main/java/com/rj/config/AliyunConfig.java index 5a033a4..0155051 100644 --- a/src/main/java/com/rj/config/AliyunConfig.java +++ b/src/main/java/com/rj/config/AliyunConfig.java @@ -86,5 +86,6 @@ public class AliyunConfig { + diff --git a/src/main/java/com/rj/controller/biz/TopSalesController.java b/src/main/java/com/rj/controller/biz/TopSalesController.java index 601c823..a339494 100644 --- a/src/main/java/com/rj/controller/biz/TopSalesController.java +++ b/src/main/java/com/rj/controller/biz/TopSalesController.java @@ -1,7 +1,6 @@ package com.rj.controller.biz; import com.rj.dto.TopSalesScoreRequestDto; -import com.rj.dto.DifyWorkflowResponseDto; import com.rj.service.biz.ITopSalesScoreResultService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -15,6 +14,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.rj.entity.bz.TopSalesScoreResult; +import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; @@ -98,6 +99,85 @@ public class TopSalesController { public ResponseEntity getByWorkflowId(@PathVariable String workflowId) { return ResponseEntity.ok(topSalesScoreResultService.getByWorkflowId(workflowId)); } + + @PostMapping("/save-mock-data") + @Operation(summary = "保存TopSales模拟评分数据") + public ResponseEntity> saveMockData(@RequestBody TopSalesScoreRequestDto requestDto) { + Map result = new HashMap<>(); + try { + // 创建模拟的评分结果 + TopSalesScoreResult mockResult = createMockScoreResult(requestDto); + + // 直接保存到数据库 + boolean saved = topSalesScoreResultService.save(mockResult); + + if (saved) { + result.put("success", true); + result.put("message", "模拟数据保存成功"); + result.put("data", mockResult); + return ResponseEntity.ok(result); + } else { + result.put("success", false); + result.put("message", "模拟数据保存失败"); + return ResponseEntity.status(500).body(result); + } + } catch (Exception e) { + result.put("success", false); + result.put("message", "保存模拟数据失败: " + e.getMessage()); + log.error("保存TopSales模拟数据失败", e); + return ResponseEntity.status(500).body(result); + } + } + + /** + * 创建模拟的评分结果 + */ + private TopSalesScoreResult createMockScoreResult(TopSalesScoreRequestDto requestDto) { + TopSalesScoreResult result = new TopSalesScoreResult(); + + // 基本信息 + result.setWorkflowId("mock_workflow_" + System.currentTimeMillis()); + result.setSalespersonName(requestDto.getSalespersonName()); + result.setSalespersonPhone(requestDto.getSalespersonPhone()); + result.setDealerName(requestDto.getDealerName()); + result.setDealerPhone(requestDto.getDealerPhone()); + result.setSrcContent(requestDto.getSrcContent()); + result.setSrcId(requestDto.getSrcId()); + result.setSrcDesc(requestDto.getSrcDesc()); + result.setStatus("success"); + result.setCreatedAt(LocalDateTime.now()); + result.setUpdatedAt(LocalDateTime.now()); + + // 生成模拟的15个维度评分 (1-10分) + result.setNaturalnessScore(generateRandomScore()); + result.setCoherenceScore(generateRandomScore()); + result.setFluencyScore(generateRandomScore()); + result.setAdvisorAggressivenessScore(generateRandomScore()); + result.setAdvisorConsistencyScore(generateRandomScore()); + result.setGreetingReceptionScore(generateRandomScore()); + result.setBrandIntroductionScore(generateRandomScore()); + result.setCustomerNeedsUnderstandingScore(generateRandomScore()); + result.setBudgetUnderstandingScore(generateRandomScore()); + result.setRecommendationScore(generateRandomScore()); + result.setSafetyIntroductionScore(generateRandomScore()); + result.setHealthEnvironmentIntroductionScore(generateRandomScore()); + result.setTechnologyIntroductionScore(generateRandomScore()); + result.setTestDriveInvitationScore(generateRandomScore()); + result.setNegotiationDealScore(generateRandomScore()); + + // 模拟其他字段 + result.setTotalTokens(1000 + (int)(Math.random() * 2000)); + result.setElapsedTime(new BigDecimal(String.format("%.2f", 1.0 + Math.random() * 5.0))); + + return result; + } + + /** + * 生成1-10分的随机评分 + */ + private Integer generateRandomScore() { + return 1 + (int)(Math.random() * 10); + } } diff --git a/src/main/java/com/rj/controller/sys/AuthController.java b/src/main/java/com/rj/controller/sys/AuthController.java index fd333f5..7921bf3 100644 --- a/src/main/java/com/rj/controller/sys/AuthController.java +++ b/src/main/java/com/rj/controller/sys/AuthController.java @@ -207,5 +207,6 @@ public class AuthController { + diff --git a/src/main/java/com/rj/controller/sys/MenuController.java b/src/main/java/com/rj/controller/sys/MenuController.java index 390df72..68b81d9 100644 --- a/src/main/java/com/rj/controller/sys/MenuController.java +++ b/src/main/java/com/rj/controller/sys/MenuController.java @@ -346,5 +346,6 @@ public class MenuController { + diff --git a/src/main/java/com/rj/controller/sys/RoleController.java b/src/main/java/com/rj/controller/sys/RoleController.java index 1b06d9d..8f7f7f8 100644 --- a/src/main/java/com/rj/controller/sys/RoleController.java +++ b/src/main/java/com/rj/controller/sys/RoleController.java @@ -316,5 +316,6 @@ public class RoleController { + diff --git a/src/main/java/com/rj/controller/sys/UserRoleController.java b/src/main/java/com/rj/controller/sys/UserRoleController.java index 110c375..6762088 100644 --- a/src/main/java/com/rj/controller/sys/UserRoleController.java +++ b/src/main/java/com/rj/controller/sys/UserRoleController.java @@ -322,5 +322,6 @@ public class UserRoleController { + diff --git a/src/main/java/com/rj/dto/DifyWorkflowResponseDto.java b/src/main/java/com/rj/dto/DifyWorkflowResponseDto.java index 29603c9..a9cbe87 100644 --- a/src/main/java/com/rj/dto/DifyWorkflowResponseDto.java +++ b/src/main/java/com/rj/dto/DifyWorkflowResponseDto.java @@ -89,5 +89,6 @@ public class DifyWorkflowResponseDto { + diff --git a/src/main/java/com/rj/mapper/CustomerProfileAnalysisMapper.java b/src/main/java/com/rj/mapper/CustomerProfileAnalysisMapper.java index b46825a..fe6f65e 100644 --- a/src/main/java/com/rj/mapper/CustomerProfileAnalysisMapper.java +++ b/src/main/java/com/rj/mapper/CustomerProfileAnalysisMapper.java @@ -33,4 +33,5 @@ public interface CustomerProfileAnalysisMapper extends BaseMapper> resp = topSalesController.saveMockData(requestDto); + if (resp != null && resp.getStatusCode().is2xxSuccessful()) { + success++; + } else { + log.warn("第{}次插入失败,返回:{}", i + 1, resp == null ? "null" : resp.getStatusCode()); + } + } + log.info("TopSales评分模拟数据任务完成,共尝试50次,成功 {} 次", success); + } catch (Exception e) { + log.error("TopSales评分模拟数据任务异常", e); + } + } + + private TopSalesScoreRequestDto buildMockTopSalesRequest() { + TopSalesScoreRequestDto requestDto = new TopSalesScoreRequestDto(); + + // 随机选择销售人员和经销商 + String[] sales = pick(SALES_PEOPLE); + String[] dealer = pick(DEALERSHIPS); + + // 设置基本信息 + requestDto.setChat(pick(MOCK_SALES_CHATS)); + requestDto.setSalespersonName(sales[1]); + requestDto.setSalespersonPhone(sales[2]); + requestDto.setDealerName(dealer[1]); + requestDto.setDealerPhone(dealer[2]); + + // 设置来源信息 + requestDto.setSrcContent(requestDto.getChat()); + requestDto.setSrcId("mock_src_" + System.currentTimeMillis() + "_" + random.nextInt(1000)); + requestDto.setSrcDesc("模拟销售对话数据 - " + sales[1] + " 在 " + dealer[1]); + + return requestDto; + } + + private String[] pick(String[][] arr) { + return arr[random.nextInt(arr.length)]; + } + + private String pick(String[] arr) { + return arr[random.nextInt(arr.length)]; + } +} diff --git a/src/main/java/com/rj/service/biz/ICustomerProfileAnalysisService.java b/src/main/java/com/rj/service/biz/ICustomerProfileAnalysisService.java index 2c6ebca..70625a0 100644 --- a/src/main/java/com/rj/service/biz/ICustomerProfileAnalysisService.java +++ b/src/main/java/com/rj/service/biz/ICustomerProfileAnalysisService.java @@ -54,4 +54,5 @@ public interface ICustomerProfileAnalysisService extends IService { + diff --git a/src/main/java/com/rj/service/sys/IUserRoleService.java b/src/main/java/com/rj/service/sys/IUserRoleService.java index 85f37e1..b1f11b2 100644 --- a/src/main/java/com/rj/service/sys/IUserRoleService.java +++ b/src/main/java/com/rj/service/sys/IUserRoleService.java @@ -55,5 +55,6 @@ public interface IUserRoleService extends IService { + diff --git a/src/main/java/com/rj/service/sys/impl/MenuServiceImpl.java b/src/main/java/com/rj/service/sys/impl/MenuServiceImpl.java index acd31bd..ca90873 100644 --- a/src/main/java/com/rj/service/sys/impl/MenuServiceImpl.java +++ b/src/main/java/com/rj/service/sys/impl/MenuServiceImpl.java @@ -59,5 +59,6 @@ public class MenuServiceImpl extends ServiceImpl implements IM + diff --git a/src/main/java/com/rj/service/sys/impl/RoleServiceImpl.java b/src/main/java/com/rj/service/sys/impl/RoleServiceImpl.java index 1c96759..cdad434 100644 --- a/src/main/java/com/rj/service/sys/impl/RoleServiceImpl.java +++ b/src/main/java/com/rj/service/sys/impl/RoleServiceImpl.java @@ -59,5 +59,6 @@ public class RoleServiceImpl extends ServiceImpl implements IR + diff --git a/src/main/java/com/rj/service/sys/impl/UserRoleServiceImpl.java b/src/main/java/com/rj/service/sys/impl/UserRoleServiceImpl.java index a3cd883..dfbeca4 100644 --- a/src/main/java/com/rj/service/sys/impl/UserRoleServiceImpl.java +++ b/src/main/java/com/rj/service/sys/impl/UserRoleServiceImpl.java @@ -59,5 +59,6 @@ public class UserRoleServiceImpl extends ServiceImpl i + diff --git a/src/main/resources/application-audio.yml b/src/main/resources/application-audio.yml index c60b588..71f490e 100644 --- a/src/main/resources/application-audio.yml +++ b/src/main/resources/application-audio.yml @@ -69,5 +69,6 @@ spring: + diff --git a/src/main/resources/mapper/AudioManagementStatisticsMapper.xml b/src/main/resources/mapper/AudioManagementStatisticsMapper.xml index f657240..7a0c282 100644 --- a/src/main/resources/mapper/AudioManagementStatisticsMapper.xml +++ b/src/main/resources/mapper/AudioManagementStatisticsMapper.xml @@ -45,5 +45,6 @@ + diff --git a/src/main/sql/add_audio_management_sales_phone.sql b/src/main/sql/add_audio_management_sales_phone.sql new file mode 100644 index 0000000..7c3a318 --- /dev/null +++ b/src/main/sql/add_audio_management_sales_phone.sql @@ -0,0 +1,10 @@ +-- 为 audio_management 表添加销售人员电话字段 +-- 执行日期: 2025-01-27 + +-- 添加销售人员电话字段 +ALTER TABLE `audio_management` +ADD COLUMN `sales_phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '销售人员电话' +AFTER `sales_name`; + + + diff --git a/src/main/sql/add_topsales_score_result_fields.sql b/src/main/sql/add_topsales_score_result_fields.sql new file mode 100644 index 0000000..b911355 --- /dev/null +++ b/src/main/sql/add_topsales_score_result_fields.sql @@ -0,0 +1,22 @@ +-- 为 topsales_score_result 表添加销售人员和经销商信息字段 +-- 执行日期: 2025-01-27 + +-- 添加销售人员姓名字段 +ALTER TABLE `topsales_score_result` +ADD COLUMN `salesperson_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '销售人员姓名' +AFTER `negotiation_deal_score`; + +-- 添加销售人员电话字段 +ALTER TABLE `topsales_score_result` +ADD COLUMN `salesperson_phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '销售人员电话' +AFTER `salesperson_name`; + +-- 添加经销商名称字段 +ALTER TABLE `topsales_score_result` +ADD COLUMN `dealer_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '经销商名称' +AFTER `salesperson_phone`; + +-- 添加经销商电话字段 +ALTER TABLE `topsales_score_result` +ADD COLUMN `dealer_phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '经销商电话' +AFTER `dealer_name`; diff --git a/src/test/java/com/rj/scheduler/AudioMockInsertDataSchedulerTest.java b/src/test/java/com/rj/scheduler/AudioMockInsertDataSchedulerTest.java new file mode 100644 index 0000000..8fc8cdf --- /dev/null +++ b/src/test/java/com/rj/scheduler/AudioMockInsertDataSchedulerTest.java @@ -0,0 +1,75 @@ +package com.rj.scheduler; + +import com.rj.entity.AudioManagement; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import java.lang.reflect.Method; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * AudioMockInsertDataScheduler 单元测试 + * 测试 generateDailyAudioData 方法,真实插入数据库 + * + * @author Test + * @since 2025-09-29 + */ +@SpringJUnitConfig +@SpringBootTest +class AudioMockInsertDataSchedulerTest { + + @Autowired + private AudioMockInsertDataScheduler audioMockInsertDataScheduler; + + @Test + void testGenerateDailyAudioData() { + try { + // 执行真实的数据生成和插入 + audioMockInsertDataScheduler.generateDailyAudioData(); + + // 如果执行到这里没有异常,说明方法执行成功 + assertTrue(true, "generateDailyAudioData 方法执行成功"); + + } catch (Exception e) { + fail("generateDailyAudioData 方法执行失败: " + e.getMessage()); + } + } + + @Test + void testBuildMockAudioManagement() throws Exception { + // 使用反射调用私有方法测试数据生成 + Method method = AudioMockInsertDataScheduler.class.getDeclaredMethod("buildMockAudioManagement"); + method.setAccessible(true); + + // 测试生成的数据 + AudioManagement audio = (AudioManagement) method.invoke(audioMockInsertDataScheduler); + + // 验证基本字段 + assertNotNull(audio.getRecordingName(), "录音名称不能为空"); + assertNotNull(audio.getRecordingTime(), "录音时间不能为空"); + assertNotNull(audio.getSalesId(), "销售ID不能为空"); + assertNotNull(audio.getSalesName(), "销售名称不能为空"); + assertNotNull(audio.getDuration(), "录音时长不能为空"); + assertNotNull(audio.getCustomerName(), "客户姓名不能为空"); + assertNotNull(audio.getCustomerPhone(), "客户手机号不能为空"); + assertNotNull(audio.getRecordingText(), "录音文本不能为空"); + + // 验证录音文本内容 + assertTrue(audio.getRecordingText().contains("销售顾问"), "录音文本应包含销售顾问对话"); + assertTrue(audio.getRecordingText().contains("客户"), "录音文本应包含客户对话"); + + // 验证数据格式 + assertTrue(audio.getCustomerPhone().matches("^1[3-9]\\d{9}$"), "客户手机号格式应正确"); + assertTrue(audio.getDuration().doubleValue() >= 5.0, "录音时长应大于等于5分钟"); + assertTrue(audio.getDuration().doubleValue() <= 60.0, "录音时长应小于等于60分钟"); + + System.out.println("生成的录音数据:"); + System.out.println("录音名称: " + audio.getRecordingName()); + System.out.println("销售顾问: " + audio.getSalesName()); + System.out.println("客户姓名: " + audio.getCustomerName()); + System.out.println("录音文本长度: " + audio.getRecordingText().length() + " 字符"); + } +} diff --git a/src/test/java/com/rj/scheduler/SalesManagementMockInsertDataSchedulerTest.java b/src/test/java/com/rj/scheduler/SalesManagementMockInsertDataSchedulerTest.java new file mode 100644 index 0000000..1f8ea98 --- /dev/null +++ b/src/test/java/com/rj/scheduler/SalesManagementMockInsertDataSchedulerTest.java @@ -0,0 +1,38 @@ +package com.rj.scheduler; + +import com.rj.entity.SalesManagement; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * SalesManagementMockInsertDataScheduler 单元测试 + * 测试 generateDailySalesData 方法,真实插入数据库 + * + * @author Test + * @since 2025-01-27 + */ +@SpringJUnitConfig +@SpringBootTest +class SalesManagementMockInsertDataSchedulerTest { + + @Autowired + private SalesManagementMockInsertDataScheduler salesManagementMockInsertDataScheduler; + + @Test + void testGenerateDailySalesData() { + try { + // 执行真实的数据生成和插入 + salesManagementMockInsertDataScheduler.generateDailySalesData(); + + + } catch (Exception e) { + fail("generateDailySalesData 方法执行失败: " + e.getMessage()); + } + } + + +} diff --git a/src/test/java/com/rj/scheduler/TopSalesMockInsertDataSchedulerTest.java b/src/test/java/com/rj/scheduler/TopSalesMockInsertDataSchedulerTest.java new file mode 100644 index 0000000..bf951a5 --- /dev/null +++ b/src/test/java/com/rj/scheduler/TopSalesMockInsertDataSchedulerTest.java @@ -0,0 +1,33 @@ +package com.rj.scheduler; + +import com.rj.controller.biz.TopSalesController; +import com.rj.dto.TopSalesScoreRequestDto; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.ResponseEntity; + +import java.util.Map; + +/** + * TopSalesMockInsertDataScheduler 测试类 + * 用于测试模拟数据生成功能 + */ +@SpringBootTest +public class TopSalesMockInsertDataSchedulerTest { + + @Autowired + private TopSalesMockInsertDataScheduler topSalesMockInsertDataScheduler; + + @Test + public void testGenerateMockData() { + try { + topSalesMockInsertDataScheduler.generateDailyTopSalesData(); + + + } catch (Exception e) { + System.err.println("测试失败: " + e.getMessage()); + e.printStackTrace(); + } + } +}