package com.klp.service.impl; import cn.hutool.core.bean.BeanUtil; import com.klp.common.core.page.TableDataInfo; import com.klp.common.core.domain.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.klp.common.utils.StringUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.klp.domain.bo.WmsMaterialCoilBo; import com.klp.domain.bo.WmsGenerateRecordBo; import com.klp.domain.vo.WmsMaterialCoilVo; import com.klp.domain.vo.WmsGenerateRecordVo; import com.klp.domain.vo.WmsWarehouseVo; import com.klp.domain.vo.WmsRawMaterialVo; import com.klp.domain.WmsMaterialCoil; import com.klp.domain.WmsStock; import com.klp.domain.bo.WmsStockBo; import com.klp.domain.vo.WmsStockVo; import com.klp.mapper.WmsMaterialCoilMapper; import com.klp.mapper.WmsStockMapper; import com.klp.service.IWmsMaterialCoilService; import com.klp.service.IWmsStockService; import com.klp.service.IWmsGenerateRecordService; import com.klp.service.IWmsWarehouseService; import com.klp.service.IWmsRawMaterialService; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Collection; import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import java.util.stream.Collectors; import java.util.HashSet; import java.util.Set; /** * 钢卷物料表Service业务层处理 * * @author Joshi * @date 2025-07-18 */ @RequiredArgsConstructor @Service public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { private final WmsMaterialCoilMapper baseMapper; private final WmsStockMapper stockMapper; private final IWmsStockService stockService; private final IWmsGenerateRecordService generateRecordService; private final IWmsWarehouseService warehouseService; private final IWmsRawMaterialService rawMaterialService; /** * 查询钢卷物料表 */ @Override public WmsMaterialCoilVo queryById(Long coilId){ WmsMaterialCoilVo vo = baseMapper.selectVoById(coilId); if (vo == null) { return null; } // 查询关联对象 fillRelatedObjects(vo); return vo; } /** * 填充关联对象信息 */ private void fillRelatedObjects(WmsMaterialCoilVo vo) { // 查询所在库区信息 if (vo.getWarehouseId() != null) { WmsWarehouseVo warehouse = warehouseService.queryById(vo.getWarehouseId()); vo.setWarehouse(warehouse); } // 查询下一库区信息 if (vo.getNextWarehouseId() != null) { WmsWarehouseVo nextWarehouse = warehouseService.queryById(vo.getNextWarehouseId()); vo.setNextWarehouse(nextWarehouse); } // 查询二维码信息 if (vo.getQrcodeRecordId() != null) { WmsGenerateRecordVo qrcodeRecord = generateRecordService.queryById(vo.getQrcodeRecordId()); vo.setQrcodeRecord(qrcodeRecord); } // 查询原材料信息(当itemType为raw_material时) if ("raw_material".equals(vo.getItemType()) && vo.getItemId() != null) { WmsRawMaterialVo rawMaterial = rawMaterialService.queryById(vo.getItemId()); vo.setRawMaterial(rawMaterial); } // 查询产品信息(当itemType为product时) // TODO: 当产品VO定义后,添加产品查询逻辑 if ("product".equals(vo.getItemType()) && vo.getItemId() != null) { // 产品查询逻辑待实现 } } /** * 查询钢卷物料表列表 */ @Override public TableDataInfo queryPageList(WmsMaterialCoilBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); return TableDataInfo.build(result); } /** * 查询钢卷物料表列表 */ @Override public List queryList(WmsMaterialCoilBo bo) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); return baseMapper.selectVoList(lqw); } private LambdaQueryWrapper buildQueryWrapper(WmsMaterialCoilBo bo) { LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.like(StringUtils.isNotBlank(bo.getEnterCoilNo()), WmsMaterialCoil::getEnterCoilNo, bo.getEnterCoilNo()); lqw.like(StringUtils.isNotBlank(bo.getCurrentCoilNo()), WmsMaterialCoil::getCurrentCoilNo, bo.getCurrentCoilNo()); lqw.like(StringUtils.isNotBlank(bo.getSupplierCoilNo()), WmsMaterialCoil::getSupplierCoilNo, bo.getSupplierCoilNo()); lqw.eq(bo.getDataType() != null, WmsMaterialCoil::getDataType, bo.getDataType()); lqw.eq(bo.getWarehouseId() != null, WmsMaterialCoil::getWarehouseId, bo.getWarehouseId()); lqw.eq(bo.getHasMergeSplit() != null, WmsMaterialCoil::getHasMergeSplit, bo.getHasMergeSplit()); lqw.eq(bo.getStatus() != null, WmsMaterialCoil::getStatus, bo.getStatus()); return lqw; } /** * 新增钢卷物料表 */ @Override @Transactional(rollbackFor = Exception.class) public Boolean insertByBo(WmsMaterialCoilBo bo) { // 1. 生成二维码 Long qrcodeRecordId = generateQrcodeForInsert(bo); bo.setQrcodeRecordId(qrcodeRecordId); // 2. 如果warehouseId为空,查找或创建stock if (bo.getWarehouseId() == null) { Long warehouseId = findOrCreateStock(bo); bo.setWarehouseId(warehouseId); } // 3. 插入钢卷数据 WmsMaterialCoil add = BeanUtil.toBean(bo, WmsMaterialCoil.class); add.setDataType(1); // 新增的钢卷默认为当前数据 validEntityBeforeSave(add); boolean flag = baseMapper.insert(add) > 0; if (flag) { bo.setCoilId(add.getCoilId()); } return flag; } /** * 生成二维码(新增) */ private Long generateQrcodeForInsert(WmsMaterialCoilBo bo) { try { Map contentMap = new HashMap<>(); String currentCoilNo = bo.getCurrentCoilNo() != null ? bo.getCurrentCoilNo() : bo.getEnterCoilNo(); contentMap.put("enter_coil_no", bo.getEnterCoilNo()); // 入场钢卷号(唯一不变) contentMap.put("current_coil_no", currentCoilNo); // 当前钢卷号(可变) // 创建steps数组 List> steps = new ArrayList<>(); Map step1 = new HashMap<>(); step1.put("step", 1); step1.put("action", "新增"); step1.put("current_coil_no", currentCoilNo); // 判断是合卷还是分卷 if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 2) { // 合卷:父编号字符串用逗号分隔 step1.put("operation", "合卷"); step1.put("parent_coil_nos", bo.getParentCoilNos()); } else if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 1) { // 分卷:多个当前钢卷号用逗号分隔 step1.put("operation", "分卷"); step1.put("current_coil_nos", currentCoilNo); } else { // 默认:当前钢卷号 step1.put("operation", "新增"); } steps.add(step1); contentMap.put("steps", steps); ObjectMapper objectMapper = new ObjectMapper(); String contentJson = objectMapper.writeValueAsString(contentMap); WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo(); recordBo.setContent(contentJson); recordBo.setSerialNumber(bo.getEnterCoilNo()); // 使用入场钢卷号作为编号 recordBo.setQrcodeType(0L); recordBo.setIsEnabled(0L); recordBo.setSize(200L); WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo); return record.getRecordId(); } catch (Exception e) { throw new RuntimeException("生成二维码失败: " + e.getMessage()); } } /** * 查找或创建stock */ private Long findOrCreateStock(WmsMaterialCoilBo bo) { if (bo.getItemType() == null || bo.getItemId() == null) { throw new RuntimeException("物品类型和物品ID不能为空"); } // 查询是否存在相同的stock WmsStockBo stockBo = new WmsStockBo(); stockBo.setItemType(bo.getItemType()); stockBo.setItemId(bo.getItemId()); List stockList = stockService.queryList(stockBo); if (!stockList.isEmpty()) { // 如果找到相同的stock,返回第一个的warehouseId return stockList.get(0).getWarehouseId(); } else { // 如果没有找到,创建一个新的stock WmsStock newStock = new WmsStock(); newStock.setItemType(bo.getItemType()); newStock.setItemId(bo.getItemId()); // 新创建的stock没有指定warehouse,可以为null stockMapper.insert(newStock); return newStock.getWarehouseId(); } } /** * 修改钢卷物料表 * 如果newCoils不为空,则进行批量更新(分卷/合卷) * 如果newCoils为空,则进行单个更新 */ @Override @Transactional(rollbackFor = Exception.class) public Boolean updateByBo(WmsMaterialCoilBo bo) { if (bo.getCoilId() == null) { throw new RuntimeException("钢卷ID不能为空"); } // 判断是否批量更新 if (bo.getNewCoils() != null && !bo.getNewCoils().isEmpty()) { // 批量更新逻辑(分卷/合卷) return updateByBatch(bo); } else { // 单个更新逻辑 return updateBySingle(bo); } } /** * 简单更新钢卷物料表 * 直接更新属性内容,不进行历史记录处理 */ @Override @Transactional(rollbackFor = Exception.class) public Boolean updateSimple(WmsMaterialCoilBo bo) { if (bo.getCoilId() == null) { throw new RuntimeException("钢卷ID不能为空"); } // 查询原钢卷是否存在 WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId()); if (oldCoil == null) { throw new RuntimeException("钢卷不存在"); } // 直接更新钢卷属性 WmsMaterialCoil updateCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class); validEntityBeforeSave(updateCoil); // 使用MyBatis-Plus的updateById方法直接更新 boolean flag = baseMapper.updateById(updateCoil) > 0; return flag; } /** * 单个更新 */ private Boolean updateBySingle(WmsMaterialCoilBo bo) { // 查询原钢卷 WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId()); if (oldCoil == null) { throw new RuntimeException("原钢卷不存在"); } // 1. 更新二维码,添加操作记录 updateQrcodeContent(oldCoil.getQrcodeRecordId(), bo); // 2. 将原数据更新为历史数据(data_type=0) LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(WmsMaterialCoil::getCoilId, bo.getCoilId()) .set(WmsMaterialCoil::getDataType, 0); // 设置为历史数据 baseMapper.update(null, updateWrapper); // 3. 插入一条新的当前数据(data_type=1) WmsMaterialCoil newCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class); newCoil.setCoilId(null); // 清空ID,让数据库自动生成新的ID newCoil.setDataType(1); // 设置为当前数据 newCoil.setQrcodeRecordId(oldCoil.getQrcodeRecordId()); // 继承二维码ID validEntityBeforeSave(newCoil); boolean flag = baseMapper.insert(newCoil) > 0; if (flag) { bo.setCoilId(newCoil.getCoilId()); } return flag; } /** * 批量更新(分卷/合卷) */ private Boolean updateByBatch(WmsMaterialCoilBo bo) { // 查询原钢卷 WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId()); if (oldCoil == null) { throw new RuntimeException("原钢卷不存在"); } // 判断是分卷还是合卷 boolean isSplit = false; boolean isMerge = false; for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) { if (newCoilBo.getHasMergeSplit() != null) { if (newCoilBo.getHasMergeSplit() == 1) { isSplit = true; break; } else if (newCoilBo.getHasMergeSplit() == 2) { isMerge = true; break; } } } // 1. 将原数据更新为历史数据(data_type=0) LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(WmsMaterialCoil::getCoilId, bo.getCoilId()) .set(WmsMaterialCoil::getDataType, 0); // 设置为历史数据 baseMapper.update(null, updateWrapper); // 2. 插入多条新的当前数据(data_type=1) List newCoils = new ArrayList<>(); List allNewCoilNos = new ArrayList<>(); // 收集所有新钢卷号 for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) { allNewCoilNos.add(newCoilBo.getCurrentCoilNo()); } if (isSplit) { // 分卷:为每个子钢卷生成独立的二维码 for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) { WmsMaterialCoil newCoil = BeanUtil.toBean(newCoilBo, WmsMaterialCoil.class); newCoil.setCoilId(null); newCoil.setDataType(1); newCoil.setEnterCoilNo(oldCoil.getEnterCoilNo()); // 为每个子钢卷生成独立二维码 Long newQrcodeId = generateQrcodeForSplit(oldCoil, newCoilBo, allNewCoilNos); newCoil.setQrcodeRecordId(newQrcodeId); validEntityBeforeSave(newCoil); baseMapper.insert(newCoil); newCoils.add(newCoil); } } else if (isMerge) { // 合卷:合并多个二维码信息为一个 Long mergedQrcodeId = generateQrcodeForMerge(oldCoil, bo.getNewCoils()); for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) { WmsMaterialCoil newCoil = BeanUtil.toBean(newCoilBo, WmsMaterialCoil.class); newCoil.setCoilId(null); newCoil.setDataType(1); newCoil.setEnterCoilNo(oldCoil.getEnterCoilNo()); newCoil.setQrcodeRecordId(mergedQrcodeId); // 所有合卷后的钢卷共享一个二维码 validEntityBeforeSave(newCoil); baseMapper.insert(newCoil); newCoils.add(newCoil); } } return true; } /** * 为分卷生成新二维码(每个子钢卷一个) */ private Long generateQrcodeForSplit(WmsMaterialCoil oldCoil, WmsMaterialCoilBo newCoilBo, List allNewCoilNos) { try { Map contentMap = new HashMap<>(); contentMap.put("enter_coil_no", oldCoil.getEnterCoilNo()); contentMap.put("current_coil_no", newCoilBo.getCurrentCoilNo()); // 复制原钢卷的历史steps List> steps = new ArrayList<>(); if (oldCoil.getQrcodeRecordId() != null) { WmsGenerateRecordVo oldRecord = generateRecordService.queryById(oldCoil.getQrcodeRecordId()); if (oldRecord != null) { ObjectMapper objectMapper = new ObjectMapper(); @SuppressWarnings("unchecked") Map oldContentMap = objectMapper.readValue(oldRecord.getContent(), Map.class); @SuppressWarnings("unchecked") List> oldSteps = (List>) oldContentMap.get("steps"); if (oldSteps != null) { steps.addAll(oldSteps); } } } // 添加分卷步骤 Map splitStep = new HashMap<>(); splitStep.put("step", steps.size() + 1); splitStep.put("action", "更新"); splitStep.put("operation", "分卷"); splitStep.put("old_current_coil_no", oldCoil.getCurrentCoilNo()); splitStep.put("new_current_coil_nos", String.join(",", allNewCoilNos)); splitStep.put("child_coils", allNewCoilNos); steps.add(splitStep); contentMap.put("steps", steps); ObjectMapper objectMapper = new ObjectMapper(); String contentJson = objectMapper.writeValueAsString(contentMap); WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo(); recordBo.setContent(contentJson); recordBo.setSerialNumber(oldCoil.getEnterCoilNo() + "-" + newCoilBo.getCurrentCoilNo()); recordBo.setQrcodeType(0L); recordBo.setIsEnabled(0L); recordBo.setSize(200L); WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo); return record.getRecordId(); } catch (Exception e) { throw new RuntimeException("生成分卷二维码失败: " + e.getMessage()); } } /** * 为合卷生成新二维码(合并多个父钢卷的二维码信息) */ private Long generateQrcodeForMerge(WmsMaterialCoil oldCoil, List newCoils) { try { if (newCoils.isEmpty()) { throw new RuntimeException("合卷后的钢卷数据不能为空"); } WmsMaterialCoilBo mergedCoilBo = newCoils.get(0); Map contentMap = new HashMap<>(); contentMap.put("enter_coil_no", oldCoil.getEnterCoilNo()); contentMap.put("current_coil_no", mergedCoilBo.getCurrentCoilNo()); // 合并所有父钢卷的历史steps List> steps = new ArrayList<>(); // 如果有父钢卷号,获取它们的二维码信息并合并 if (mergedCoilBo.getParentCoilNos() != null && !mergedCoilBo.getParentCoilNos().trim().isEmpty()) { String[] parentCoilNos = mergedCoilBo.getParentCoilNos().split(","); for (String parentCoilNo : parentCoilNos) { // 查找父钢卷 LambdaQueryWrapper parentLqw = Wrappers.lambdaQuery(); parentLqw.eq(WmsMaterialCoil::getCurrentCoilNo, parentCoilNo.trim()) .eq(WmsMaterialCoil::getDataType, 1); List parentCoils = baseMapper.selectList(parentLqw); if (!parentCoils.isEmpty() && parentCoils.get(0).getQrcodeRecordId() != null) { WmsGenerateRecordVo parentQr = generateRecordService.queryById(parentCoils.get(0).getQrcodeRecordId()); if (parentQr != null) { ObjectMapper objectMapper = new ObjectMapper(); @SuppressWarnings("unchecked") Map parentContentMap = objectMapper.readValue(parentQr.getContent(), Map.class); @SuppressWarnings("unchecked") List> parentSteps = (List>) parentContentMap.get("steps"); if (parentSteps != null) { steps.addAll(parentSteps); } } } } } // 添加原钢卷的历史 if (oldCoil.getQrcodeRecordId() != null) { WmsGenerateRecordVo oldRecord = generateRecordService.queryById(oldCoil.getQrcodeRecordId()); if (oldRecord != null) { ObjectMapper objectMapper = new ObjectMapper(); @SuppressWarnings("unchecked") Map oldContentMap = objectMapper.readValue(oldRecord.getContent(), Map.class); @SuppressWarnings("unchecked") List> oldSteps = (List>) oldContentMap.get("steps"); if (oldSteps != null) { steps.addAll(oldSteps); } } } // 添加合卷步骤 Map mergeStep = new HashMap<>(); mergeStep.put("step", steps.size() + 1); mergeStep.put("action", "更新"); mergeStep.put("operation", "合卷"); mergeStep.put("parent_coil_nos", mergedCoilBo.getParentCoilNos()); mergeStep.put("new_current_coil_no", mergedCoilBo.getCurrentCoilNo()); steps.add(mergeStep); contentMap.put("steps", steps); ObjectMapper objectMapper = new ObjectMapper(); String contentJson = objectMapper.writeValueAsString(contentMap); WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo(); recordBo.setContent(contentJson); recordBo.setSerialNumber(oldCoil.getEnterCoilNo() + "-" + mergedCoilBo.getCurrentCoilNo()); recordBo.setQrcodeType(0L); recordBo.setIsEnabled(0L); recordBo.setSize(200L); WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo); return record.getRecordId(); } catch (Exception e) { throw new RuntimeException("生成合卷二维码失败: " + e.getMessage()); } } /** * 更新二维码内容(单个更新) */ private void updateQrcodeContent(Long qrcodeRecordId, WmsMaterialCoilBo bo) { try { // 获取原钢卷信息 WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId()); // 获取原二维码记录 WmsGenerateRecordVo oldRecord = generateRecordService.queryById(qrcodeRecordId); if (oldRecord == null) { throw new RuntimeException("二维码记录不存在"); } // 解析现有content ObjectMapper objectMapper = new ObjectMapper(); Map contentMap = objectMapper.readValue(oldRecord.getContent(), Map.class); // 获取现有steps @SuppressWarnings("unchecked") List> steps = (List>) contentMap.get("steps"); if (steps == null) { steps = new ArrayList<>(); } // 添加新的step,记录钢卷号的变化 Map newStep = new HashMap<>(); newStep.put("step", steps.size() + 1); newStep.put("action", "更新"); newStep.put("old_current_coil_no", oldCoil.getCurrentCoilNo()); // 原当前钢卷号 newStep.put("new_current_coil_no", bo.getCurrentCoilNo()); // 新当前钢卷号 // 判断操作类型 if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 2) { newStep.put("operation", "合卷"); newStep.put("parent_coil_nos", bo.getParentCoilNos()); } else if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 1) { newStep.put("operation", "分卷"); newStep.put("new_current_coil_nos", bo.getCurrentCoilNo()); } else { newStep.put("operation", "更新"); } steps.add(newStep); contentMap.put("steps", steps); // 更新当前钢卷号到最外层(方便快速查看) contentMap.put("current_coil_no", bo.getCurrentCoilNo()); // 更新二维码记录 String newContentJson = objectMapper.writeValueAsString(contentMap); WmsGenerateRecordBo updateBo = new WmsGenerateRecordBo(); updateBo.setRecordId(qrcodeRecordId); updateBo.setContent(newContentJson); generateRecordService.updateByBo(updateBo); } catch (Exception e) { throw new RuntimeException("更新二维码失败: " + e.getMessage()); } } /** * 保存前的数据校验 */ private void validEntityBeforeSave(WmsMaterialCoil entity){ //TODO 做一些数据校验,如唯一约束 } /** * 批量删除钢卷物料表 */ @Override public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { if(isValid){ //TODO 做一些业务上的校验,判断是否需要校验 } return baseMapper.deleteBatchIds(ids) > 0; } /** * 钢卷溯源查询 * 根据入场钢卷号查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库 * * @param enterCoilNo 入场钢卷号 * @param currentCoilNo 当前钢卷号(可选,用于查询特定子钢卷) * @return 溯源结果(包含二维码信息和数据库记录) */ @Override public Map queryTrace(String enterCoilNo, String currentCoilNo) { try { // 1. 根据入场钢卷号查询二维码记录 WmsGenerateRecordBo qrBo = new WmsGenerateRecordBo(); qrBo.setSerialNumber(enterCoilNo); List qrRecords = generateRecordService.queryList(qrBo); if (qrRecords.isEmpty()) { throw new RuntimeException("未找到对应的二维码记录"); } // 取第一个(应该只有一个) WmsGenerateRecordVo qrRecord = qrRecords.get(0); // 2. 解析二维码content中的steps ObjectMapper objectMapper = new ObjectMapper(); @SuppressWarnings("unchecked") Map contentMap = objectMapper.readValue(qrRecord.getContent(), Map.class); @SuppressWarnings("unchecked") List> steps = (List>) contentMap.get("steps"); // 3. 从steps中提取所有钢卷号 Set coilNos = new HashSet<>(); if (steps != null) { for (Map step : steps) { // 提取各种可能的钢卷号字段 extractCoilNo(step, "current_coil_no", coilNos); extractCoilNo(step, "new_current_coil_no", coilNos); extractCoilNo(step, "old_current_coil_no", coilNos); extractCoilNo(step, "new_current_coil_nos", coilNos); extractCoilNo(step, "merged_from", coilNos); extractCoilNo(step, "parent_coil_nos", coilNos); } } // 4. 如果指定了当前钢卷号,过滤出相关的钢卷号 Set filteredCoilNos = coilNos; if (currentCoilNo != null && !currentCoilNo.trim().isEmpty()) { final String filterValue = currentCoilNo; // 用于lambda的final变量 filteredCoilNos = coilNos.stream() .filter(coilNo -> coilNo.contains(filterValue)) .collect(Collectors.toSet()); } // 5. 根据提取的钢卷号反向查询数据库 List result = new ArrayList<>(); if (!filteredCoilNos.isEmpty()) { LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo); // 查询包含提取出的钢卷号的记录 final Set finalCoilNos = filteredCoilNos; // 用于lambda的final变量 lqw.and(wrapper -> { int count = 0; for (String coilNo : finalCoilNos) { if (count == 0) { wrapper.like(WmsMaterialCoil::getCurrentCoilNo, coilNo); } else { wrapper.or().like(WmsMaterialCoil::getCurrentCoilNo, coilNo); } count++; } }); lqw.orderByAsc(WmsMaterialCoil::getCreateTime); result = baseMapper.selectVoList(lqw); } // 6. 构建返回结果 Map resultMap = new HashMap<>(); resultMap.put("qrcode", qrRecord); resultMap.put("steps", steps); resultMap.put("records", result); return resultMap; } catch (Exception e) { throw new RuntimeException("溯源查询失败: " + e.getMessage()); } } /** * 从step中提取钢卷号 */ private void extractCoilNo(Map step, String fieldName, Set coilNos) { Object value = step.get(fieldName); if (value != null) { String strValue = value.toString(); if (strValue.contains(",")) { // 如果是逗号分隔的多个钢卷号,分割后添加 String[] coilArray = strValue.split(","); for (String coilNo : coilArray) { coilNos.add(coilNo.trim()); } } else { coilNos.add(strValue.trim()); } } } }