Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X
This commit is contained in:
@@ -161,15 +161,15 @@ public class WmsMaterialCoilController extends BaseController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 钢卷溯源查询
|
* 钢卷溯源查询
|
||||||
* 根据入场钢卷号查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
* 根据钢卷ID查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
||||||
*
|
*
|
||||||
* @param enterCoilNo 入场钢卷号
|
* @param coilId 钢卷ID
|
||||||
* @param currentCoilNo 当前钢卷号(可选参数,用于查询特定子钢卷)
|
* @param currentCoilNo 当前钢卷号(可选参数,用于查询特定子钢卷)
|
||||||
*/
|
*/
|
||||||
@GetMapping("/trace")
|
@GetMapping("/trace")
|
||||||
public R<Map<String, Object>> trace(@RequestParam @NotBlank(message = "入场钢卷号不能为空") String enterCoilNo,
|
public R<Map<String, Object>> trace(@RequestParam @NotNull(message = "钢卷ID不能为空") Long coilId,
|
||||||
@RequestParam(required = false) String currentCoilNo) {
|
@RequestParam(required = false) String currentCoilNo) {
|
||||||
Map<String, Object> traceResult = iWmsMaterialCoilService.queryTrace(enterCoilNo, currentCoilNo);
|
Map<String, Object> traceResult = iWmsMaterialCoilService.queryTrace(coilId, currentCoilNo);
|
||||||
return R.ok(traceResult);
|
return R.ok(traceResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,13 +60,13 @@ public interface IWmsMaterialCoilService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 钢卷溯源查询
|
* 钢卷溯源查询
|
||||||
* 根据入场钢卷号查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
* 根据钢卷ID查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
||||||
*
|
*
|
||||||
* @param enterCoilNo 入场钢卷号
|
* @param coilId 钢卷ID
|
||||||
* @param currentCoilNo 当前钢卷号(可选,用于查询特定子钢卷)
|
* @param currentCoilNo 当前钢卷号(可选,用于查询特定子钢卷)
|
||||||
* @return 溯源结果(包含二维码信息和数据库记录)
|
* @return 溯源结果(包含二维码信息和数据库记录)
|
||||||
*/
|
*/
|
||||||
Map<String, Object> queryTrace(String enterCoilNo, String currentCoilNo);
|
Map<String, Object> queryTrace(Long coilId, String currentCoilNo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询各个库区中不同类型的钢卷分布情况
|
* 查询各个库区中不同类型的钢卷分布情况
|
||||||
|
|||||||
@@ -1910,105 +1910,67 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 钢卷溯源查询
|
* 钢卷溯源查询
|
||||||
* 根据入场钢卷号查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
* 根据钢卷ID查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
||||||
*
|
*
|
||||||
* @param enterCoilNo 入场钢卷号
|
* @param coilId 钢卷ID
|
||||||
* @param currentCoilNo 当前钢卷号(可选,用于查询特定子钢卷)
|
* @param currentCoilNo 当前钢卷号(可选,用于查询特定子钢卷)
|
||||||
* @return 溯源结果(包含二维码信息和数据库记录)
|
* @return 溯源结果(包含二维码信息和数据库记录)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> queryTrace(String enterCoilNo, String currentCoilNo) {
|
public Map<String, Object> queryTrace(Long coilId, String currentCoilNo) {
|
||||||
try {
|
try {
|
||||||
// 优化1: 使用LIKE查询替代查询所有记录,大幅提升性能
|
WmsMaterialCoilVo coilVo = baseMapper.selectVoById(coilId);
|
||||||
List<WmsGenerateRecordVo> allQrRecords = new ArrayList<>();
|
if (coilVo == null) {
|
||||||
|
throw new RuntimeException("未找到对应的钢卷记录");
|
||||||
// 首先查询主二维码(以入场钢卷号为序列号的)
|
|
||||||
WmsGenerateRecordBo qrBo = new WmsGenerateRecordBo();
|
|
||||||
qrBo.setSerialNumber(enterCoilNo);
|
|
||||||
List<WmsGenerateRecordVo> mainQrRecords = generateRecordService.queryList(qrBo);
|
|
||||||
allQrRecords.addAll(mainQrRecords);
|
|
||||||
|
|
||||||
// 优化:使用LIKE查询所有以该入场钢卷号开头的二维码(分卷后的二维码)
|
|
||||||
// 而不是查询所有记录然后在内存中过滤
|
|
||||||
LambdaQueryWrapper<com.klp.domain.WmsGenerateRecord> splitWrapper = Wrappers.lambdaQuery();
|
|
||||||
splitWrapper.like(com.klp.domain.WmsGenerateRecord::getSerialNumber, enterCoilNo + "-");
|
|
||||||
List<WmsGenerateRecordVo> splitRecords = generateRecordMapper.selectVoList(splitWrapper);
|
|
||||||
|
|
||||||
// 去重:使用recordId作为唯一标识
|
|
||||||
Set<Long> existingRecordIds = allQrRecords.stream()
|
|
||||||
.map(WmsGenerateRecordVo::getRecordId)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
for (WmsGenerateRecordVo record : splitRecords) {
|
|
||||||
if (record.getRecordId() != null && !existingRecordIds.contains(record.getRecordId())) {
|
|
||||||
allQrRecords.add(record);
|
|
||||||
existingRecordIds.add(record.getRecordId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allQrRecords.isEmpty()) {
|
Long qrcodeRecordId = coilVo.getQrcodeRecordId();
|
||||||
|
if (qrcodeRecordId == null) {
|
||||||
|
throw new RuntimeException("该钢卷未关联二维码记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
WmsGenerateRecordVo qrRecord = generateRecordService.queryById(qrcodeRecordId);
|
||||||
|
if (qrRecord == null) {
|
||||||
throw new RuntimeException("未找到对应的二维码记录");
|
throw new RuntimeException("未找到对应的二维码记录");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 优化2: ObjectMapper在循环外创建,避免重复创建
|
String enterCoilNo = coilVo.getEnterCoilNo();
|
||||||
|
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
// 2. 合并所有二维码的steps信息,去重并重新编号
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Map<String, Object>> uniqueSteps = new HashMap<>(); // 用于去重
|
Map<String, Object> contentMap = objectMapper.readValue(qrRecord.getContent(), Map.class);
|
||||||
Set<String> allCoilNos = new HashSet<>();
|
|
||||||
|
|
||||||
// 收集所有操作人用户名
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
|
||||||
|
|
||||||
|
Set<String> allCoilNos = new HashSet<>();
|
||||||
Set<String> operatorUsernames = new HashSet<>();
|
Set<String> operatorUsernames = new HashSet<>();
|
||||||
|
|
||||||
for (WmsGenerateRecordVo qrRecord : allQrRecords) {
|
if (steps != null) {
|
||||||
@SuppressWarnings("unchecked")
|
for (Map<String, Object> step : steps) {
|
||||||
Map<String, Object> contentMap = (Map<String, Object>) objectMapper.readValue(qrRecord.getContent(), Map.class);
|
extractCoilNo(step, "current_coil_no", allCoilNos);
|
||||||
|
extractCoilNo(step, "new_current_coil_no", allCoilNos);
|
||||||
|
extractCoilNo(step, "old_current_coil_no", allCoilNos);
|
||||||
|
extractCoilNo(step, "new_current_coil_nos", allCoilNos);
|
||||||
|
extractCoilNo(step, "merged_from", allCoilNos);
|
||||||
|
extractCoilNo(step, "parent_coil_nos", allCoilNos);
|
||||||
|
extractCoilId(step, "coil_id", allCoilNos);
|
||||||
|
extractCoilId(step, "old_coil_id", allCoilNos);
|
||||||
|
extractCoilId(step, "parent_coil_ids", allCoilNos);
|
||||||
|
extractCoilId(step, "child_coil_ids", allCoilNos);
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
Object operator = step.get("operator");
|
||||||
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
|
if (operator != null) {
|
||||||
|
operatorUsernames.add(operator.toString());
|
||||||
if (steps != null) {
|
|
||||||
for (Map<String, Object> step : steps) {
|
|
||||||
// 创建唯一标识:操作类型 + 相关钢卷号
|
|
||||||
String stepKey = createStepKey(step);
|
|
||||||
|
|
||||||
// 如果是新的步骤,添加到唯一步骤集合中
|
|
||||||
if (!uniqueSteps.containsKey(stepKey)) {
|
|
||||||
Map<String, Object> uniqueStep = new HashMap<>(step);
|
|
||||||
uniqueStep.put("qrcode_serial", qrRecord.getSerialNumber());
|
|
||||||
uniqueStep.put("qrcode_id", qrRecord.getRecordId());
|
|
||||||
uniqueSteps.put(stepKey, uniqueStep);
|
|
||||||
|
|
||||||
// 收集操作人用户名
|
|
||||||
Object operator = step.get("operator");
|
|
||||||
if (operator != null) {
|
|
||||||
operatorUsernames.add(operator.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提取钢卷号
|
|
||||||
extractCoilNo(step, "current_coil_no", allCoilNos);
|
|
||||||
extractCoilNo(step, "new_current_coil_no", allCoilNos);
|
|
||||||
extractCoilNo(step, "old_current_coil_no", allCoilNos);
|
|
||||||
extractCoilNo(step, "new_current_coil_nos", allCoilNos);
|
|
||||||
extractCoilNo(step, "merged_from", allCoilNos);
|
|
||||||
extractCoilNo(step, "parent_coil_nos", allCoilNos);
|
|
||||||
extractCoilId(step, "coil_id", allCoilNos);
|
|
||||||
extractCoilId(step, "old_coil_id", allCoilNos);
|
|
||||||
extractCoilId(step, "parent_coil_ids", allCoilNos);
|
|
||||||
// 从分卷步骤中提取子钢卷IDs
|
|
||||||
extractCoilId(step, "child_coil_ids", allCoilNos);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取操作人昵称映射
|
|
||||||
Map<String, String> operatorNicknameMap = getOperatorNicknames(operatorUsernames);
|
Map<String, String> operatorNicknameMap = getOperatorNicknames(operatorUsernames);
|
||||||
|
|
||||||
// 转换为列表并按原始步骤号排序(保持时间顺序)
|
List<Map<String, Object>> allSteps = new ArrayList<>(steps != null ? steps : new ArrayList<>());
|
||||||
List<Map<String, Object>> allSteps = new ArrayList<>(uniqueSteps.values());
|
|
||||||
|
|
||||||
// 按原始步骤号排序,保持实际操作的时间顺序
|
|
||||||
allSteps.sort((a, b) -> {
|
allSteps.sort((a, b) -> {
|
||||||
Integer stepA = (Integer) a.get("step");
|
Integer stepA = (Integer) a.get("step");
|
||||||
Integer stepB = (Integer) b.get("step");
|
Integer stepB = (Integer) b.get("step");
|
||||||
@@ -2017,13 +1979,12 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
|||||||
return stepA.compareTo(stepB);
|
return stepA.compareTo(stepB);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 重新编号(保持连续性)
|
|
||||||
for (int i = 0; i < allSteps.size(); i++) {
|
for (int i = 0; i < allSteps.size(); i++) {
|
||||||
allSteps.get(i).put("display_step", i + 1);
|
allSteps.get(i).put("display_step", i + 1);
|
||||||
// 保留原始步骤号用于调试
|
|
||||||
allSteps.get(i).put("original_step", allSteps.get(i).get("step"));
|
allSteps.get(i).put("original_step", allSteps.get(i).get("step"));
|
||||||
|
allSteps.get(i).put("qrcode_serial", qrRecord.getSerialNumber());
|
||||||
|
allSteps.get(i).put("qrcode_id", qrRecord.getRecordId());
|
||||||
|
|
||||||
// 替换操作人为昵称
|
|
||||||
Object operator = allSteps.get(i).get("operator");
|
Object operator = allSteps.get(i).get("operator");
|
||||||
if (operator != null) {
|
if (operator != null) {
|
||||||
String username = operator.toString();
|
String username = operator.toString();
|
||||||
@@ -2032,7 +1993,6 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 如果指定了当前钢卷号,过滤出相关的钢卷号
|
|
||||||
Set<String> filteredCoilNos = allCoilNos;
|
Set<String> filteredCoilNos = allCoilNos;
|
||||||
if (currentCoilNo != null && !currentCoilNo.trim().isEmpty()) {
|
if (currentCoilNo != null && !currentCoilNo.trim().isEmpty()) {
|
||||||
final String filterValue = currentCoilNo;
|
final String filterValue = currentCoilNo;
|
||||||
@@ -2041,20 +2001,16 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 优化3: 使用IN查询替代多个OR条件,提升查询性能
|
|
||||||
// 4. 根据提取的钢卷号反向查询数据库
|
|
||||||
List<WmsMaterialCoilVo> result = new ArrayList<>();
|
List<WmsMaterialCoilVo> result = new ArrayList<>();
|
||||||
if (!filteredCoilNos.isEmpty()) {
|
if (!filteredCoilNos.isEmpty() && StringUtils.isNotBlank(enterCoilNo)) {
|
||||||
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
|
||||||
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
|
|
||||||
|
|
||||||
// 优化:使用IN查询替代多个OR条件(当钢卷号数量较少时)
|
|
||||||
// 如果数量太多(>1000),分批查询避免SQL过长
|
|
||||||
List<String> coilNoList = new ArrayList<>(filteredCoilNos);
|
List<String> coilNoList = new ArrayList<>(filteredCoilNos);
|
||||||
if (coilNoList.size() <= 1000) {
|
if (coilNoList.size() <= 1000) {
|
||||||
|
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
|
||||||
lqw.in(WmsMaterialCoil::getCurrentCoilNo, coilNoList);
|
lqw.in(WmsMaterialCoil::getCurrentCoilNo, coilNoList);
|
||||||
|
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
|
||||||
|
result = baseMapper.selectVoList(lqw);
|
||||||
} else {
|
} else {
|
||||||
// 分批查询
|
|
||||||
int batchSize = 1000;
|
int batchSize = 1000;
|
||||||
for (int i = 0; i < coilNoList.size(); i += batchSize) {
|
for (int i = 0; i < coilNoList.size(); i += batchSize) {
|
||||||
int end = Math.min(i + batchSize, coilNoList.size());
|
int end = Math.min(i + batchSize, coilNoList.size());
|
||||||
@@ -2068,36 +2024,26 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coilNoList.size() <= 1000) {
|
|
||||||
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
|
|
||||||
result = baseMapper.selectVoList(lqw);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 优化4: 批量填充关联对象,避免N+1查询
|
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
fillRelatedObjectsBatch(result);
|
fillRelatedObjectsBatch(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有找到记录,尝试查询所有相关的钢卷(包括历史数据)
|
if (result.isEmpty() && StringUtils.isNotBlank(enterCoilNo)) {
|
||||||
if (result.isEmpty()) {
|
|
||||||
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
||||||
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
|
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
|
||||||
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
|
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
|
||||||
result = baseMapper.selectVoList(lqw);
|
result = baseMapper.selectVoList(lqw);
|
||||||
|
|
||||||
// 优化:批量填充关联对象
|
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
fillRelatedObjectsBatch(result);
|
fillRelatedObjectsBatch(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 构建返回结果
|
|
||||||
Map<String, Object> resultMap = new HashMap<>();
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
resultMap.put("qrcode", allQrRecords.get(0)); // 主二维码
|
resultMap.put("qrcode", qrRecord);
|
||||||
resultMap.put("all_qrcodes", allQrRecords); // 所有相关二维码
|
resultMap.put("steps", allSteps);
|
||||||
resultMap.put("steps", allSteps); // 所有步骤
|
resultMap.put("records", result);
|
||||||
resultMap.put("records", result); // 所有钢卷记录
|
|
||||||
|
|
||||||
return resultMap;
|
return resultMap;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user