refactor(wms): 修改钢卷溯源查询方法参数和优化查询逻辑
- 将溯源查询方法参数从入场钢卷号改为钢卷ID - 通过钢卷ID直接获取钢卷信息和关联的二维码记录 - 移除原有的复杂二维码查询逻辑,简化为直接通过钢卷ID获取 - 优化钢卷记录查询方式,移除重复和不必要的查询步骤 - 简化溯源步骤处理逻辑,移除重复步骤合并功能 - 调整返回结果结构,精简二维码相关信息 - 优化数据库查询性能,使用更直接的关联查询方式
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 当前钢卷号(可选参数,用于查询特定子钢卷)
|
||||
*/
|
||||
@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) {
|
||||
Map<String, Object> traceResult = iWmsMaterialCoilService.queryTrace(enterCoilNo, currentCoilNo);
|
||||
Map<String, Object> traceResult = iWmsMaterialCoilService.queryTrace(coilId, currentCoilNo);
|
||||
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 当前钢卷号(可选,用于查询特定子钢卷)
|
||||
* @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 当前钢卷号(可选,用于查询特定子钢卷)
|
||||
* @return 溯源结果(包含二维码信息和数据库记录)
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> queryTrace(String enterCoilNo, String currentCoilNo) {
|
||||
public Map<String, Object> queryTrace(Long coilId, String currentCoilNo) {
|
||||
try {
|
||||
// 优化1: 使用LIKE查询替代查询所有记录,大幅提升性能
|
||||
List<WmsGenerateRecordVo> allQrRecords = new ArrayList<>();
|
||||
|
||||
// 首先查询主二维码(以入场钢卷号为序列号的)
|
||||
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());
|
||||
}
|
||||
WmsMaterialCoilVo coilVo = baseMapper.selectVoById(coilId);
|
||||
if (coilVo == null) {
|
||||
throw new RuntimeException("未找到对应的钢卷记录");
|
||||
}
|
||||
|
||||
if (allQrRecords.isEmpty()) {
|
||||
Long qrcodeRecordId = coilVo.getQrcodeRecordId();
|
||||
if (qrcodeRecordId == null) {
|
||||
throw new RuntimeException("该钢卷未关联二维码记录");
|
||||
}
|
||||
|
||||
WmsGenerateRecordVo qrRecord = generateRecordService.queryById(qrcodeRecordId);
|
||||
if (qrRecord == null) {
|
||||
throw new RuntimeException("未找到对应的二维码记录");
|
||||
}
|
||||
|
||||
// 优化2: ObjectMapper在循环外创建,避免重复创建
|
||||
String enterCoilNo = coilVo.getEnterCoilNo();
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
// 2. 合并所有二维码的steps信息,去重并重新编号
|
||||
Map<String, Map<String, Object>> uniqueSteps = new HashMap<>(); // 用于去重
|
||||
Set<String> allCoilNos = new HashSet<>();
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> contentMap = objectMapper.readValue(qrRecord.getContent(), Map.class);
|
||||
|
||||
// 收集所有操作人用户名
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
|
||||
|
||||
Set<String> allCoilNos = new HashSet<>();
|
||||
Set<String> operatorUsernames = new HashSet<>();
|
||||
|
||||
for (WmsGenerateRecordVo qrRecord : allQrRecords) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> contentMap = (Map<String, Object>) objectMapper.readValue(qrRecord.getContent(), Map.class);
|
||||
if (steps != null) {
|
||||
for (Map<String, Object> step : steps) {
|
||||
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")
|
||||
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
|
||||
|
||||
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);
|
||||
Object operator = step.get("operator");
|
||||
if (operator != null) {
|
||||
operatorUsernames.add(operator.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取操作人昵称映射
|
||||
Map<String, String> operatorNicknameMap = getOperatorNicknames(operatorUsernames);
|
||||
|
||||
// 转换为列表并按原始步骤号排序(保持时间顺序)
|
||||
List<Map<String, Object>> allSteps = new ArrayList<>(uniqueSteps.values());
|
||||
List<Map<String, Object>> allSteps = new ArrayList<>(steps != null ? steps : new ArrayList<>());
|
||||
|
||||
// 按原始步骤号排序,保持实际操作的时间顺序
|
||||
allSteps.sort((a, b) -> {
|
||||
Integer stepA = (Integer) a.get("step");
|
||||
Integer stepB = (Integer) b.get("step");
|
||||
@@ -2017,13 +1979,12 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
||||
return stepA.compareTo(stepB);
|
||||
});
|
||||
|
||||
// 重新编号(保持连续性)
|
||||
for (int i = 0; i < allSteps.size(); i++) {
|
||||
allSteps.get(i).put("display_step", i + 1);
|
||||
// 保留原始步骤号用于调试
|
||||
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");
|
||||
if (operator != null) {
|
||||
String username = operator.toString();
|
||||
@@ -2032,7 +1993,6 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 如果指定了当前钢卷号,过滤出相关的钢卷号
|
||||
Set<String> filteredCoilNos = allCoilNos;
|
||||
if (currentCoilNo != null && !currentCoilNo.trim().isEmpty()) {
|
||||
final String filterValue = currentCoilNo;
|
||||
@@ -2041,20 +2001,16 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
// 优化3: 使用IN查询替代多个OR条件,提升查询性能
|
||||
// 4. 根据提取的钢卷号反向查询数据库
|
||||
List<WmsMaterialCoilVo> result = new ArrayList<>();
|
||||
if (!filteredCoilNos.isEmpty()) {
|
||||
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
|
||||
|
||||
// 优化:使用IN查询替代多个OR条件(当钢卷号数量较少时)
|
||||
// 如果数量太多(>1000),分批查询避免SQL过长
|
||||
if (!filteredCoilNos.isEmpty() && StringUtils.isNotBlank(enterCoilNo)) {
|
||||
List<String> coilNoList = new ArrayList<>(filteredCoilNos);
|
||||
if (coilNoList.size() <= 1000) {
|
||||
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
|
||||
lqw.in(WmsMaterialCoil::getCurrentCoilNo, coilNoList);
|
||||
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
|
||||
result = baseMapper.selectVoList(lqw);
|
||||
} else {
|
||||
// 分批查询
|
||||
int batchSize = 1000;
|
||||
for (int i = 0; i < coilNoList.size(); i += batchSize) {
|
||||
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()) {
|
||||
fillRelatedObjectsBatch(result);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到记录,尝试查询所有相关的钢卷(包括历史数据)
|
||||
if (result.isEmpty()) {
|
||||
if (result.isEmpty() && StringUtils.isNotBlank(enterCoilNo)) {
|
||||
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
|
||||
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
|
||||
result = baseMapper.selectVoList(lqw);
|
||||
|
||||
// 优化:批量填充关联对象
|
||||
if (!result.isEmpty()) {
|
||||
fillRelatedObjectsBatch(result);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 构建返回结果
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("qrcode", allQrRecords.get(0)); // 主二维码
|
||||
resultMap.put("all_qrcodes", allQrRecords); // 所有相关二维码
|
||||
resultMap.put("steps", allSteps); // 所有步骤
|
||||
resultMap.put("records", result); // 所有钢卷记录
|
||||
resultMap.put("qrcode", qrRecord);
|
||||
resultMap.put("steps", allSteps);
|
||||
resultMap.put("records", result);
|
||||
|
||||
return resultMap;
|
||||
} catch (Exception e) {
|
||||
|
||||
Reference in New Issue
Block a user