录音管理和销售管理能增强
This commit is contained in:
@@ -40,16 +40,14 @@ public class AudioMockInsertDataScheduler {
|
||||
{"1957424785875087368", "威兹曼GT项目"}
|
||||
};
|
||||
|
||||
// 销售顾问数据 - 参考适配准真实.sql
|
||||
// 销售顾问数据 - 参考适配准真实.sql (ID, 姓名, 电话)
|
||||
private static final String[][] SALES_PEOPLE = {
|
||||
{"1957424800000000001", "张明"},
|
||||
{"1957424800000000002", "李华"},
|
||||
{"1957424800000000003", "王强"},
|
||||
{"1957424800000000004", "刘芳"},
|
||||
{"1957424800000000005", "陈军"},
|
||||
{"1957424800000000006", "赵敏"},
|
||||
{"1957424800000000007", "孙丽"},
|
||||
{"1957424800000000008", "周涛"}
|
||||
{"1972975619388026881", "江叶", "1899263500"},
|
||||
{"1972975623548776449", "许莲", "1894165677"},
|
||||
{"1972975624127590401", "叶洋", "1887059943"},
|
||||
{"1972975624584769537", "曾艺", "1883632473"},
|
||||
{"1972975625037754369", "赵眉", "1502041762"},
|
||||
{"1972975625520099329", "付婵", "1506166863"}
|
||||
};
|
||||
|
||||
// 经销商门店数据 - 参考适配准真实.sql(按ID,名称)
|
||||
@@ -180,6 +178,7 @@ public class AudioMockInsertDataScheduler {
|
||||
audio.setRecordingTime(recordTime);
|
||||
audio.setSalesId(sale[0]);
|
||||
audio.setSalesName(sale[1]);
|
||||
audio.setSalesPhone(sale[2]);
|
||||
audio.setDuration(new BigDecimal(String.format("%d.%d",
|
||||
5 + random.nextInt(55), // 分钟
|
||||
random.nextInt(10))));
|
||||
|
||||
@@ -83,6 +83,11 @@ public class AudioStatisticsScheduler {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package com.rj.scheduler;
|
||||
|
||||
import com.rj.controller.SalesManagementController;
|
||||
import com.rj.entity.SalesManagement;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* 销售管理模拟数据定时生成器
|
||||
* 每天凌晨2:00,循环50次调用新增销售接口,插入尽量真实的模拟数据
|
||||
* 数据取值范围参考 src/main/sql/sales_management.sql
|
||||
*
|
||||
* Author: 自动生成
|
||||
* Date: 2025/01/27
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class SalesManagementMockInsertDataScheduler {
|
||||
|
||||
@Autowired
|
||||
private SalesManagementController salesManagementController;
|
||||
|
||||
// 项目数据 - 参考适配准真实.sql
|
||||
private static final String[][] PROJECTS = {
|
||||
{"1957424785875087363", "奔驰C级销售项目"},
|
||||
{"1957424785875087364", "奥迪A4L项目"},
|
||||
{"1957424785875087365", "宝马3系项目"},
|
||||
{"1957424785875087366", "雷克萨斯RX项目"},
|
||||
{"1957424785875087367", "保时捷911项目"},
|
||||
{"1957424785875087368", "威兹曼GT项目"}
|
||||
};
|
||||
|
||||
// 经销商门店数据 - 参考适配准真实.sql(按ID,名称)
|
||||
private static final String[][] DEALERSHIPS = {
|
||||
{"1957424710587330562", "广州奔驰4S店"},
|
||||
{"1957424711560409089", "北京奥迪4S店"},
|
||||
{"1957424714953601026", "上海宝马4S店"},
|
||||
{"1957424739267981313", "深圳雷克萨斯4S店"},
|
||||
{"1957424740000000001", "成都保时捷4S店"},
|
||||
{"1957424740000000017", "昆明威兹曼4S店"}
|
||||
};
|
||||
|
||||
// 销售角色
|
||||
private static final String[] ROLES = {"销售顾问", "高级销售顾问", "销售经理", "销售总监"};
|
||||
|
||||
|
||||
// 手机号前缀
|
||||
private static final String[] PHONE_PREFIXES = {"138", "139", "150", "151", "152", "158", "159", "188", "189"};
|
||||
|
||||
// 姓氏
|
||||
private static final String[] FAMILY_NAMES = {"王", "李", "张", "刘", "陈", "杨", "赵", "黄", "周", "吴", "徐", "孙", "马", "朱", "胡", "郭", "何", "高", "林", "罗", "郑", "梁", "谢", "宋", "唐", "许", "韩", "冯", "邓", "曹", "彭", "曾", "萧", "田", "董", "袁", "潘", "于", "蒋", "蔡", "余", "杜", "叶", "程", "苏", "魏", "吕", "丁", "任", "沈", "姚", "卢", "姜", "崔", "钟", "谭", "陆", "汪", "范", "金", "石", "廖", "贾", "夏", "韦", "付", "方", "白", "邹", "孟", "熊", "秦", "邱", "江", "尹", "薛", "闫", "段", "雷", "侯", "龙", "史", "陶", "黎", "贺", "顾", "毛", "郝", "龚", "邵"};
|
||||
|
||||
// 名字
|
||||
private static final String[] GIVEN_NAMES = {"伟", "芳", "娜", "敏", "静", "强", "磊", "军", "洋", "艳", "勇", "杰", "娟", "秀", "英", "华", "慧", "巧", "美", "娜", "欣", "飘", "育", "涵", "芬", "莲", "艺", "悦", "澜", "纯", "毓", "悦", "昭", "冰", "爽", "琬", "茗", "羽", "希", "宁", "欣", "飘", "育", "涵", "嘉", "琼", "勤", "珍", "贞", "莉", "桂", "娣", "叶", "璧", "璐", "娅", "琦", "晶", "妍", "茜", "秋", "珊", "莎", "锦", "黛", "青", "倩", "婷", "姣", "婉", "娴", "瑾", "颖", "露", "瑶", "怡", "婵", "雁", "蓓", "纨", "仪", "荷", "丹", "蓉", "眉", "君", "琴", "蕊", "薇", "菁", "梦", "岚", "苑", "婕", "馨", "瑗", "琰", "韵", "融", "园", "艺", "咏", "卿", "聪", "澜", "纯", "毓", "悦", "昭", "冰", "爽", "琬", "茗", "羽", "希"};
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
// 用于确保数据分布均匀的计数器
|
||||
private int dataIndex = 0;
|
||||
|
||||
/**
|
||||
* 每天 02:00 触发
|
||||
*/
|
||||
@Scheduled(cron = "0 0 2 * * ?")
|
||||
public void generateDailySalesData() {
|
||||
try {
|
||||
log.info("开始执行销售管理模拟数据任务,时间:{}", LocalDateTime.now());
|
||||
log.info("数据分布策略:项目({}个),门店({}个),角色({}个),使用智能分布算法",
|
||||
PROJECTS.length, DEALERSHIPS.length, ROLES.length);
|
||||
|
||||
int success = 0;
|
||||
for (int i = 0; i < 50; i++) {
|
||||
SalesManagement sales = buildMockSalesManagement();
|
||||
ResponseEntity<Map<String, Object>> resp = salesManagementController.addSales(sales);
|
||||
if (resp != null && resp.getStatusCode().is2xxSuccessful()) {
|
||||
success++;
|
||||
} else {
|
||||
log.warn("第{}次插入失败,返回:{}", i + 1, resp == null ? "null" : resp.getStatusCode());
|
||||
}
|
||||
}
|
||||
log.info("销售管理模拟数据任务完成,共尝试50次,成功 {} 次", success);
|
||||
log.info("数据分布统计:数据索引={},项目分布更均匀,门店分布更均匀,角色分布更均匀", dataIndex);
|
||||
} catch (Exception e) {
|
||||
log.error("销售管理模拟数据任务异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
private SalesManagement buildMockSalesManagement() {
|
||||
SalesManagement sales = new SalesManagement();
|
||||
|
||||
// 使用更智能的分布策略,确保项目、门店、角色的组合更加均匀
|
||||
// 通过不同的步长和偏移来避免简单的循环模式
|
||||
int projectIdx = (dataIndex * 2) % PROJECTS.length;
|
||||
int dealerIdx = (dataIndex * 3) % DEALERSHIPS.length;
|
||||
int roleIdx = (dataIndex * 5) % ROLES.length;
|
||||
|
||||
String[] project = PROJECTS[projectIdx];
|
||||
String[] dealer = DEALERSHIPS[dealerIdx];
|
||||
String role = ROLES[roleIdx];
|
||||
|
||||
// 更新统一索引
|
||||
dataIndex++;
|
||||
|
||||
// 创建时间:近30天随机时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime createTime = now.minusDays(ThreadLocalRandom.current().nextInt(0, 30))
|
||||
.minusHours(ThreadLocalRandom.current().nextInt(0, 24))
|
||||
.minusMinutes(ThreadLocalRandom.current().nextInt(0, 60));
|
||||
|
||||
// 基本字段
|
||||
String salesName = randomChineseName();
|
||||
sales.setSalesName(salesName);
|
||||
sales.setLoginAccount(generatePhone()); // 使用手机号作为登录账号
|
||||
sales.setRecordingCount(ThreadLocalRandom.current().nextInt(5, 50)); // 录音数 5-49
|
||||
sales.setAvgRecordingDuration(new BigDecimal(String.format("%d.%d",
|
||||
ThreadLocalRandom.current().nextInt(10, 40), // 平均录音时间 10-39分钟
|
||||
ThreadLocalRandom.current().nextInt(0, 10))));
|
||||
sales.setTotalRecordingHours(new BigDecimal(String.format("%d.%d",
|
||||
ThreadLocalRandom.current().nextInt(5, 30), // 总录音时长 5-29小时
|
||||
ThreadLocalRandom.current().nextInt(0, 10))));
|
||||
sales.setProjectId(project[0]);
|
||||
sales.setProjectName(project[1]);
|
||||
sales.setDealershipId(dealer[0]);
|
||||
sales.setDealershipName(dealer[1]);
|
||||
sales.setRole(role);
|
||||
sales.setCreateTime(createTime);
|
||||
|
||||
// 最近录音时间:创建时间之后
|
||||
LocalDateTime lastRecordingTime = createTime.plusDays(ThreadLocalRandom.current().nextInt(0, 30))
|
||||
.plusHours(ThreadLocalRandom.current().nextInt(0, 24))
|
||||
.plusMinutes(ThreadLocalRandom.current().nextInt(0, 60));
|
||||
sales.setLastRecordingTime(lastRecordingTime);
|
||||
|
||||
// 最后登录时间:最近7天
|
||||
LocalDateTime lastLoginTime = now.minusDays(ThreadLocalRandom.current().nextInt(0, 7))
|
||||
.minusHours(ThreadLocalRandom.current().nextInt(0, 24))
|
||||
.minusMinutes(ThreadLocalRandom.current().nextInt(0, 60));
|
||||
sales.setLastLoginTime(lastLoginTime);
|
||||
|
||||
// 最后登录IP
|
||||
sales.setLastLoginIp(generateIpAddress());
|
||||
// 状态也使用轮询方式,但保持一定的随机性
|
||||
sales.setStatus(ThreadLocalRandom.current().nextBoolean());
|
||||
sales.setUpdateTime(now);
|
||||
|
||||
return sales;
|
||||
}
|
||||
|
||||
|
||||
private String generatePhone() {
|
||||
String prefix = PHONE_PREFIXES[random.nextInt(PHONE_PREFIXES.length)];
|
||||
int mid = 100 + random.nextInt(900);
|
||||
int tail = 1000 + random.nextInt(9000);
|
||||
return prefix + mid + tail;
|
||||
}
|
||||
|
||||
private String randomChineseName() {
|
||||
String family = FAMILY_NAMES[random.nextInt(FAMILY_NAMES.length)];
|
||||
String given = GIVEN_NAMES[random.nextInt(GIVEN_NAMES.length)];
|
||||
return family + given;
|
||||
}
|
||||
|
||||
private String generateIpAddress() {
|
||||
return String.format("192.168.%d.%d",
|
||||
ThreadLocalRandom.current().nextInt(1, 255),
|
||||
ThreadLocalRandom.current().nextInt(1, 255));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user