| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.mes.device.entity.GlassInfo; |
| | | import com.mes.device.mapper.DeviceGlassInfoMapper; |
| | | import com.mes.device.service.EngineeringSequenceService; |
| | | import com.mes.device.service.GlassInfoService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.cloud.context.config.annotation.RefreshScope; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.ZoneId; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static java.util.stream.IntStream.range; |
| | | |
| | | /** |
| | | * 玻璃信息服务实现类 |
| | |
| | | @RefreshScope |
| | | @Service("deviceGlassInfoService") |
| | | public class GlassInfoServiceImpl extends ServiceImpl<DeviceGlassInfoMapper, GlassInfo> implements GlassInfoService { |
| | | |
| | | @Autowired |
| | | private EngineeringSequenceService engineeringSequenceService; |
| | | |
| | | @Override |
| | | public GlassInfo getGlassInfo(String glassId) { |
| | |
| | | return result; |
| | | } |
| | | |
| | | // 工程号生成:P + yyMMdd + 序号(2位) |
| | | AtomicInteger seq = new AtomicInteger(1); |
| | | final String engineerId = generateEngineerId(firstValue(excelRows, "glassId"), seq.getAndIncrement()); |
| | | // 工程号:代表整个Excel表,优先使用Excel中的工程号(从第一行或任意一行获取),如果所有行都没有则自动生成 |
| | | String engineerIdFromExcel = null; |
| | | for (Map<String, Object> row : excelRows) { |
| | | String engineeringId = str(row.get("engineeringId")); |
| | | if (engineeringId != null && !engineeringId.trim().isEmpty()) { |
| | | engineerIdFromExcel = engineeringId.trim(); |
| | | break; // 找到第一个非空的工程号就使用 |
| | | } |
| | | } |
| | | final String engineerId = engineerIdFromExcel != null |
| | | ? engineerIdFromExcel |
| | | : engineeringSequenceService.generateEngineeringId(new Date()); |
| | | final String filmsIdDefault = firstValue(excelRows, "filmsId", "白玻"); |
| | | final double thicknessDefault = parseDouble(firstValue(excelRows, "thickness"), 0d); |
| | | |
| | |
| | | final String filmsIdDefaultFinal = filmsIdDefault; |
| | | final double thicknessDefaultFinal = thicknessDefault; |
| | | |
| | | List<Map<String, Object>> glassInfolList = excelRows.stream() |
| | | .flatMap(row -> { |
| | | int qty = (int) parseDouble(row.getOrDefault("quantity", 1), 1); |
| | | if (qty <= 0) qty = 1; |
| | | String glassId = str(row.get("glassId")); |
| | | String filmsId = strOrDefault(row.get("filmsId"), filmsIdDefaultFinal); |
| | | // 生成日期字符串(yyMMdd格式),用于流程卡ID生成 |
| | | LocalDate localDate = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); |
| | | String dateStr = localDate.format(DateTimeFormatter.ofPattern("yyMMdd")); |
| | | |
| | | // 检查是否有流程卡ID:如果所有行的流程卡ID都为空,则所有记录共享同一个流程卡ID |
| | | boolean allFlowCardIdEmpty = excelRows.stream() |
| | | .allMatch(row -> { |
| | | String flowCardId = str(row.get("flowCardId")); |
| | | String productName = str(row.get("productName")); |
| | | String customerName = str(row.get("customerName")); |
| | | double width = parseDouble(row.get("width"), 0d); |
| | | double height = parseDouble(row.get("height"), 0d); |
| | | double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal); |
| | | return flowCardId == null || flowCardId.trim().isEmpty(); |
| | | }); |
| | | // 如果所有流程卡ID都为空,生成一个共享的流程卡ID |
| | | String sharedFlowCardId = allFlowCardIdEmpty ? "NG" + dateStr + "01A001" : null; |
| | | |
| | | // 用于存储每个玻璃ID对应的流程卡ID(同一玻璃ID的多个玻璃共享同一个流程卡ID) |
| | | Map<String, String> glassIdFlowCardIdMap = new HashMap<>(); |
| | | |
| | | // 用于按 flowCardId 计数 temperingFeedSequence |
| | | Map<String, Integer> temperingFeedSequenceCounter = new HashMap<>(); |
| | | // 用于按 flowCardId 分配 temperingLayoutId |
| | | Map<String, Integer> temperingLayoutIdMap = new HashMap<>(); |
| | | AtomicInteger nextTemperingLayoutId = new AtomicInteger(1); |
| | | |
| | | // 先建立原片映射,用于后续匹配 rawSequence |
| | | Map<String, Integer> rawSequenceMap = new HashMap<>(); |
| | | for (Map<String, Object> row : excelRows) { |
| | | double width = parseDouble(row.get("width"), 0d); |
| | | double height = parseDouble(row.get("length"), 0d); |
| | | double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal); |
| | | String filmsId = strOrDefault(row.get("filmsId"), filmsIdDefaultFinal); |
| | | String key = width + "_" + height + "_" + thickness + "_" + filmsId; |
| | | if (!rawSequenceMap.containsKey(key)) { |
| | | rawSequenceMap.put(key, rawSequenceMap.size() + 1); |
| | | } |
| | | } |
| | | |
| | | int finalQty = qty; |
| | | return range(0, qty).mapToObj(idx -> { |
| | | String finalGlassId = finalQty > 1 ? glassId + "_" + (idx + 1) : glassId; |
| | | String finalFlowCardId = flowCardId.isEmpty() ? finalGlassId : flowCardId; |
| | | Map<String, Object> m = new HashMap<>(); |
| | | m.put("xAxis", 0); |
| | | m.put("xCoordinate", 0); |
| | | m.put("yAxis", 0); |
| | | m.put("yCoordinate", 0); |
| | | m.put("glassId", finalGlassId); |
| | | m.put("engineerId", engineerIdFinal); |
| | | m.put("flowCardId", finalFlowCardId); |
| | | m.put("productSortNumber", idx + 1); |
| | | m.put("hollowCombineDirection", "0"); |
| | | m.put("width", width); |
| | | m.put("height", height); |
| | | m.put("thickness", thickness); |
| | | m.put("filmsId", filmsId); |
| | | m.put("layer", 0); |
| | | m.put("totalLayer", 0); |
| | | m.put("edgWidth", width); |
| | | m.put("edgHeight", height); |
| | | m.put("isMultiple", 0); |
| | | m.put("maxWidth", width); |
| | | m.put("maxHeight", height); |
| | | m.put("isHorizontal", 0); |
| | | m.put("rawSequence", 0); |
| | | m.put("temperingLayoutId", 0); |
| | | m.put("temperingFeedSequence", 0); |
| | | m.put("angle", 0); |
| | | m.put("ruleId", 0); |
| | | m.put("combine", 0); |
| | | m.put("markIcon", ""); |
| | | m.put("filmRemove", 0); |
| | | m.put("flowCardSequence", flowCardId + "/" + (idx + 1)); |
| | | m.put("process", ""); |
| | | m.put("rawAngle", 0); |
| | | m.put("graphNo", 0); |
| | | m.put("processParam", ""); |
| | | return m; |
| | | }); |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | List<Map<String, Object>> glassInfolList = new ArrayList<>(); |
| | | for (Map<String, Object> row : excelRows) { |
| | | Object qtyObj = row.getOrDefault("quantity", 1); |
| | | int qty = parseDouble(qtyObj, 1) > 0 ? (int) parseDouble(qtyObj, 1) : 1; |
| | | |
| | | String glassId = str(row.get("glassId")); |
| | | String filmsId = strOrDefault(row.get("filmsId"), filmsIdDefaultFinal); |
| | | // 流程卡ID:如果Excel中有,使用Excel的;如果为空,使用共享的流程卡ID |
| | | String flowCardIdFromExcel = str(row.get("flowCardId")); |
| | | String flowCardId; |
| | | if (flowCardIdFromExcel != null && !flowCardIdFromExcel.trim().isEmpty()) { |
| | | // Excel中有流程卡ID,使用Excel的 |
| | | flowCardId = flowCardIdFromExcel.trim(); |
| | | } else { |
| | | // Excel中流程卡ID为空,使用共享的流程卡ID |
| | | flowCardId = sharedFlowCardId != null ? sharedFlowCardId : getOrGenerateFlowCardId(glassId, dateStr, glassIdFlowCardIdMap); |
| | | } |
| | | // 去掉尾部 "/数字"(如果有) |
| | | String baseFlowCardId = flowCardId.replaceFirst("/\\d+$", ""); |
| | | |
| | | // 层号:如果Excel中有,使用Excel的;如果没有,默认1 |
| | | Object layerObj = row.get("layer"); |
| | | int layer = layerObj != null ? (int) parseDouble(layerObj, 1) : 1; |
| | | if (layer <= 0) { |
| | | layer = 1; |
| | | } |
| | | |
| | | // orderNumber 是整型(玻璃类型),从 Excel 读取或使用默认值 1 |
| | | Object orderNumberObj = row.get("orderNumber"); |
| | | final Integer finalOrderNumber = orderNumberObj != null |
| | | ? (int) parseDouble(orderNumberObj, 1) |
| | | : 1; |
| | | String productName = str(row.get("productName")); |
| | | String customerName = str(row.get("customerName")); |
| | | double width = parseDouble(row.get("width"), 0d); |
| | | double height = parseDouble(row.get("length"), 0d); |
| | | double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal); |
| | | |
| | | // 计算 rawSequence |
| | | String rawKey = width + "_" + height + "_" + thickness + "_" + filmsId; |
| | | Integer rawSequence = rawSequenceMap.get(rawKey); |
| | | |
| | | int finalQty = qty; |
| | | log.info("解析到数量:row={}, quantity={}, 最终qty={}", row, qtyObj, finalQty); |
| | | |
| | | // 按 flowCardId 分配 temperingLayoutId |
| | | Integer temperingLayoutId = temperingLayoutIdMap.computeIfAbsent(baseFlowCardId, k -> nextTemperingLayoutId.getAndIncrement()); |
| | | |
| | | // 为同一行的多个玻璃生成数据 |
| | | for (int idx = 0; idx < qty; idx++) { |
| | | String baseGlassId = engineerIdFinal + glassId; |
| | | String finalGlassId = finalQty > 1 ? baseGlassId + (idx + 1) : baseGlassId; |
| | | |
| | | // 按 flowCardId 递增 temperingFeedSequence |
| | | int temperingFeedSequence = temperingFeedSequenceCounter.compute(baseFlowCardId, (k, v) -> (v == null ? 0 : v) + 1); |
| | | String finalFlowCardSequence = baseFlowCardId + "/" + 1; |
| | | |
| | | log.debug("生成玻璃信息: glassId={}, idx={}, baseFlowCardId={}, finalFlowCardSequence={}, temperingLayoutId={}, temperingFeedSequence={}", |
| | | glassId, idx, baseFlowCardId, finalFlowCardSequence, temperingLayoutId, temperingFeedSequence); |
| | | |
| | | Map<String, Object> m = new HashMap<>(); |
| | | m.put("xAxis", 0); |
| | | m.put("xCoordinate", 0); |
| | | m.put("yAxis", 0); |
| | | m.put("yCoordinate", 0); |
| | | m.put("glassId", finalGlassId); |
| | | m.put("engineerId", engineerIdFinal); |
| | | m.put("flowCardId", baseFlowCardId); |
| | | m.put("orderNumber", finalOrderNumber); |
| | | m.put("productSortNumber", 1); |
| | | m.put("hollowCombineDirection", ""); |
| | | m.put("width", width); |
| | | m.put("height", height); |
| | | m.put("thickness", thickness); |
| | | m.put("filmsId", filmsId); |
| | | m.put("layer", layer); |
| | | m.put("totalLayer", 1); |
| | | m.put("edgWidth", width); |
| | | m.put("edgHeight", height); |
| | | m.put("isMultiple", finalQty > 1 ? 1 : 0); |
| | | m.put("maxWidth", width); |
| | | m.put("maxHeight", height); |
| | | m.put("isHorizontal", 0); |
| | | m.put("rawSequence", rawSequence != null ? rawSequence : 0); |
| | | m.put("temperingLayoutId", temperingLayoutId); |
| | | m.put("temperingFeedSequence", temperingFeedSequence); |
| | | m.put("angle", 0); |
| | | m.put("ruleId", 0); |
| | | m.put("combine", 0); |
| | | m.put("markIcon", ""); |
| | | m.put("filmRemove", 0); |
| | | m.put("flowCardSequence", finalFlowCardSequence); |
| | | m.put("process", ""); |
| | | m.put("rawAngle", 0); |
| | | m.put("graphNo", 0); |
| | | m.put("processParam", ""); |
| | | glassInfolList.add(m); |
| | | } |
| | | } |
| | | |
| | | // 原片信息去重 |
| | | Map<String, Map<String, Object>> rawGlassMap = new HashMap<>(); |
| | | for (Map<String, Object> row : excelRows) { |
| | | double width = parseDouble(row.get("width"), 0d); |
| | | double height = parseDouble(row.get("height"), 0d); |
| | | double height = parseDouble(row.get("length"), 0d); |
| | | double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal); |
| | | String filmsId = strOrDefault(row.get("filmsId"), filmsIdDefaultFinal); |
| | | String key = width + "_" + height + "_" + thickness + "_" + filmsId; |
| | |
| | | |
| | | List<Map<String, Object>> engineeringRawQueueList = rawGlassMap.values().stream().collect(Collectors.toList()); |
| | | |
| | | // 流程卡信息 |
| | | // 流程卡信息(需要统计每个 flowCardId 的实际玻璃数量,考虑 quantity) |
| | | Map<String, Map<String, Object>> flowCardMap = new HashMap<>(); |
| | | for (Map<String, Object> row : excelRows) { |
| | | String glassId = str(row.get("glassId")); |
| | | String flowCardId = str(row.get("flowCardId")); |
| | | if (flowCardId.isEmpty()) { |
| | | flowCardId = glassId; |
| | | // 流程卡ID:如果Excel中有,使用Excel的;如果为空,使用共享的流程卡ID(与glassInfolList逻辑一致) |
| | | String flowCardIdFromExcel = str(row.get("flowCardId")); |
| | | String flowCardId; |
| | | if (flowCardIdFromExcel != null && !flowCardIdFromExcel.trim().isEmpty()) { |
| | | // Excel中有流程卡ID,使用Excel的 |
| | | flowCardId = flowCardIdFromExcel.trim(); |
| | | } else { |
| | | // Excel中流程卡ID为空,使用共享的流程卡ID |
| | | flowCardId = sharedFlowCardId != null ? sharedFlowCardId : getOrGenerateFlowCardId(glassId, dateStr, glassIdFlowCardIdMap); |
| | | } |
| | | // 去掉尾部 "/数字"(如果有) |
| | | flowCardId = flowCardId.replaceFirst("/\\d+$", ""); |
| | | // orderNumber 是整型(玻璃类型),从 Excel 读取或使用默认值 1 |
| | | Object orderNumberObj = row.get("orderNumber"); |
| | | Integer orderNumber = orderNumberObj != null |
| | | ? (int) parseDouble(orderNumberObj, 1) |
| | | : 1; |
| | | Object qtyObj = row.getOrDefault("quantity", 1); |
| | | int qty = parseDouble(qtyObj, 1) > 0 ? (int) parseDouble(qtyObj, 1) : 1; |
| | | double width = parseDouble(row.get("width"), 0d); |
| | | double height = parseDouble(row.get("height"), 0d); |
| | | double height = parseDouble(row.get("length"), 0d); |
| | | double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal); |
| | | String filmsId = strOrDefault(row.get("filmsId"), filmsIdDefaultFinal); |
| | | |
| | | String productName = str(row.get("productName")); |
| | | String customerName = str(row.get("customerName")); |
| | | |
| | |
| | | m.put("height", height); |
| | | m.put("thickness", thickness); |
| | | m.put("filmsId", filmsId); |
| | | m.put("totalLayer", 0); |
| | | m.put("layer", 0); |
| | | m.put("glassTotal", 1); |
| | | m.put("totalLayer", 1); |
| | | m.put("layer", 1); |
| | | m.put("glassTotal", qty); // 使用实际数量 |
| | | m.put("orderNumber", orderNumber); |
| | | m.put("productName", productName); |
| | | m.put("customerName", customerName); |
| | | flowCardMap.put(flowCardId, m); |
| | | } else { |
| | | int count = (int) exist.getOrDefault("glassTotal", 1); |
| | | exist.put("glassTotal", count + 1); |
| | | int count = (int) exist.getOrDefault("glassTotal", 0); |
| | | exist.put("glassTotal", count + qty); // 累加数量 |
| | | } |
| | | } |
| | | List<Map<String, Object>> flowCardInfoList = flowCardMap.values().stream().collect(Collectors.toList()); |
| | |
| | | .mapToDouble(m -> parseDouble(m.get("rawGlassWidth"), 0d) * parseDouble(m.get("rawGlassHeight"), 0d) / 1_000_000d) |
| | | .sum(); |
| | | |
| | | // 计算最大负载尺寸(用于钢化参数) |
| | | double maxLoadWidth = glassInfolList.stream() |
| | | .mapToDouble(m -> parseDouble(m.get("width"), 0d)) |
| | | .max().orElse(2000); |
| | | double maxLoadLength = glassInfolList.stream() |
| | | .mapToDouble(m -> parseDouble(m.get("height"), 0d)) |
| | | .max().orElse(3000); |
| | | |
| | | // 生成钢化参数 |
| | | List<Map<String, Object>> temperingParameterList = new ArrayList<>(); |
| | | Map<String, Object> temperingParam = new HashMap<>(); |
| | | temperingParam.put("engineerId", engineerIdFinal); |
| | | temperingParam.put("heatMode", 1); |
| | | temperingParam.put("chaosPct", 50); |
| | | temperingParam.put("maxLoadPct", 100); |
| | | temperingParam.put("loadWidth", (int) Math.round(maxLoadWidth)); |
| | | temperingParam.put("loadLength", (int) Math.round(maxLoadLength)); |
| | | temperingParam.put("xSpace", 50); |
| | | temperingParam.put("ySpace", 50); |
| | | temperingParam.put("rotateMode", 0); |
| | | temperingParam.put("allowRotate", 0); |
| | | temperingParam.put("tempering", 1); |
| | | temperingParam.put("curtainWall", 0); |
| | | temperingParameterList.add(temperingParam); |
| | | |
| | | result.put("engineerId", engineerIdFinal); |
| | | result.put("engineerName", "工程_" + engineerIdFinal); |
| | | result.put("engineerName", thicknessDefaultFinal + "mm" + filmsIdDefaultFinal); |
| | | result.put("avgAvailability", "90"); |
| | | result.put("validAvailability", "90"); |
| | | result.put("lastAvailability", "90"); |
| | |
| | | return result; |
| | | } |
| | | |
| | | // 日期格式化器(线程不安全,使用ThreadLocal保证线程安全) |
| | | private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd"); |
| | | |
| | | // 数字匹配正则(预编译提升性能) |
| | | private static final Pattern DIGIT_PATTERN = Pattern.compile("\\d+"); |
| | | |
| | | /** |
| | | * 生成工程师ID |
| | | * 格式规则:P + 年月日(yyMMdd) + 两位序号 |
| | | * 序号优先从glassId中提取末尾两位数字,否则使用传入的index补零 |
| | | * |
| | | * @param glassId 玻璃ID(可为null,用于提取数字序号) |
| | | * @param index 备用序号(当glassId无有效数字时使用) |
| | | * @return 格式化的工程师ID(如:P25010801) |
| | | */ |
| | | private String generateEngineerId(Object glassId, int index) { |
| | | // 1. 生成日期前缀(yyMMdd) |
| | | String base = LocalDate.now().format(DATE_FORMATTER); |
| | | |
| | | // 2. 初始化序号(两位补零) |
| | | String seq = String.format("%02d", index); |
| | | |
| | | // 3. 从glassId中提取末尾两位数字(覆盖默认序号) |
| | | if (glassId != null) { |
| | | String glassIdStr = glassId.toString(); |
| | | Matcher matcher = DIGIT_PATTERN.matcher(glassIdStr); |
| | | String lastDigitStr = null; |
| | | |
| | | // 遍历匹配所有数字段,取最后一个 |
| | | while (matcher.find()) { |
| | | lastDigitStr = matcher.group(); |
| | | } |
| | | |
| | | // 若数字段长度≥2,取最后两位;否则保留原序号 |
| | | if (lastDigitStr != null && lastDigitStr.length() >= 2) { |
| | | seq = lastDigitStr.substring(lastDigitStr.length() - 2); |
| | | } |
| | | } |
| | | |
| | | return "P" + base + seq; |
| | | } |
| | | |
| | | /** |
| | | * 提取List中第一个Map的指定key值(默认空字符串) |
| | |
| | | return def; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取或生成流程卡ID |
| | | * 如果已存在则返回,否则生成新的流程卡ID并缓存 |
| | | * 前端格式:原始glassId + 两位序号(如"101"、"102"、"201"),通过除以100去掉最后两位提取原始glassId |
| | | * |
| | | * @param glassId 玻璃ID(如"101"、"102"、"201") |
| | | * @param dateStr 日期字符串(yyMMdd格式) |
| | | * @param glassIdFlowCardIdMap 玻璃ID到流程卡ID的映射缓存 |
| | | * @return 流程卡ID(格式:NG + yyMMdd + 序号(两位) + A001) |
| | | */ |
| | | private String getOrGenerateFlowCardId(String glassId, String dateStr, Map<String, String> glassIdFlowCardIdMap) { |
| | | String flowCardId = glassIdFlowCardIdMap.get(glassId); |
| | | if (flowCardId == null) { |
| | | // 从glassId中提取原始数字:101 -> 1, 102 -> 1, 201 -> 2 |
| | | int sequence = 1; |
| | | if (glassId != null && !glassId.trim().isEmpty()) { |
| | | try { |
| | | String cleaned = glassId.trim().split("[\\r\\n\\t\\s]+")[0]; |
| | | if (cleaned.matches("\\d+")) { |
| | | int num = Integer.parseInt(cleaned); |
| | | // 如果长度>=3,除以100去掉最后两位(前端追加的序号) |
| | | sequence = (cleaned.length() >= 3 && num >= 100) ? num / 100 : (num > 0 ? num : 1); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("从glassId中提取原始数字失败: glassId={}", glassId, e); |
| | | } |
| | | } |
| | | flowCardId = "NG" + dateStr + String.format("%02d", sequence) + "A001"; |
| | | glassIdFlowCardIdMap.put(glassId, flowCardId); |
| | | log.info("为玻璃ID {} 生成流程卡ID: flowCardId={}", glassId, flowCardId); |
| | | } |
| | | return flowCardId; |
| | | } |
| | | |
| | | /** |
| | | * 保留两位小数(四舍五入) |
| | |
| | | return Math.round(v * 100.0) / 100.0; |
| | | } |
| | | |
| | | @Override |
| | | public List<GlassInfo> getGlassInfosByEngineeringId(String engineeringId) { |
| | | if (engineeringId == null || engineeringId.trim().isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | try { |
| | | return baseMapper.selectByEngineeringId(engineeringId.trim()); |
| | | } catch (Exception e) { |
| | | log.error("根据工程号查询玻璃信息失败, engineeringId={}", engineeringId, e); |
| | | return Collections.emptyList(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void saveGlassInfosFromExcel(List<Map<String, Object>> excelRows, String engineeringId) { |
| | | if (excelRows == null || excelRows.isEmpty() || engineeringId == null || engineeringId.trim().isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | // 如果工程号已存在,先删除该工程号下的旧数据,实现覆盖更新 |
| | | List<GlassInfo> existingGlassInfos = getGlassInfosByEngineeringId(engineeringId.trim()); |
| | | if (!existingGlassInfos.isEmpty()) { |
| | | log.info("检测到工程号 {} 已存在 {} 条记录,将删除旧数据并更新", engineeringId, existingGlassInfos.size()); |
| | | deleteGlassInfosByEngineeringId(engineeringId.trim()); |
| | | } |
| | | |
| | | List<GlassInfo> glassInfos = new ArrayList<>(); |
| | | Date now = new Date(); |
| | | |
| | | for (Map<String, Object> row : excelRows) { |
| | | String glassId = str(row.get("glassId")); |
| | | if (glassId == null || glassId.trim().isEmpty()) { |
| | | continue; |
| | | } |
| | | |
| | | int qty = (int) parseDouble(row.getOrDefault("quantity", 1), 1); |
| | | if (qty <= 0) qty = 1; |
| | | |
| | | double width = parseDouble(row.get("width"), 0d); |
| | | double length = parseDouble(row.get("length"), 0d); |
| | | double thickness = parseDouble(row.get("thickness"), 0d); |
| | | |
| | | // 与导入规则保持一致:glassId 前加工程号前缀,数量>1时追加序号 |
| | | String baseGlassId = engineeringId.trim() + glassId; |
| | | for (int idx = 0; idx < qty; idx++) { |
| | | String finalGlassId = qty > 1 ? baseGlassId + (idx + 1) : baseGlassId; |
| | | |
| | | GlassInfo glassInfo = new GlassInfo(); |
| | | glassInfo.setGlassId(finalGlassId); |
| | | glassInfo.setEngineeringId(engineeringId.trim()); |
| | | glassInfo.setGlassLength((int) Math.round(length)); |
| | | glassInfo.setGlassWidth((int) Math.round(width)); |
| | | glassInfo.setGlassThickness(BigDecimal.valueOf(thickness)); |
| | | glassInfo.setStatus(GlassInfo.Status.ACTIVE); |
| | | glassInfo.setState(0); |
| | | glassInfo.setCreatedTime(now); |
| | | glassInfo.setUpdatedTime(now); |
| | | glassInfo.setCreatedBy("system"); |
| | | glassInfo.setUpdatedBy("system"); |
| | | |
| | | glassInfos.add(glassInfo); |
| | | } |
| | | } |
| | | |
| | | if (!glassInfos.isEmpty()) { |
| | | batchSaveOrUpdateGlassInfo(glassInfos); |
| | | log.info("已保存 {} 条玻璃信息到本地数据库,工程号: {}", glassInfos.size(), engineeringId); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateGlassStateAfterScan(String glassId, Integer width, Integer height, Integer workLine) { |
| | | if (glassId == null || glassId.trim().isEmpty()) { |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | // 查询已存在的玻璃信息 |
| | | GlassInfo existing = baseMapper.selectByGlassId(glassId.trim()); |
| | | if (existing == null) { |
| | | log.debug("玻璃信息不存在,无法更新状态: glassId={}", glassId); |
| | | return false; |
| | | } |
| | | |
| | | // 更新状态为1(已扫码交互) |
| | | LambdaUpdateWrapper<GlassInfo> wrapper = new LambdaUpdateWrapper<>(); |
| | | wrapper.eq(GlassInfo::getGlassId, glassId.trim()) |
| | | .eq(GlassInfo::getIsDeleted, 0) |
| | | .set(GlassInfo::getState, 1) |
| | | .set(GlassInfo::getUpdatedTime, new Date()) |
| | | .set(GlassInfo::getUpdatedBy, "system"); |
| | | |
| | | // 如果提供了尺寸信息,也更新尺寸 |
| | | if (width != null) { |
| | | wrapper.set(GlassInfo::getGlassWidth, width); |
| | | } |
| | | if (height != null) { |
| | | wrapper.set(GlassInfo::getGlassLength, height); |
| | | } |
| | | if (workLine != null) { |
| | | wrapper.set(GlassInfo::getWorkLine, workLine); |
| | | } |
| | | |
| | | boolean updated = this.update(wrapper); |
| | | if (updated) { |
| | | log.info("已更新玻璃信息状态为已扫码交互: glassId={}, state=1", glassId); |
| | | } |
| | | return updated; |
| | | } catch (Exception e) { |
| | | log.error("更新玻璃信息状态失败: glassId={}", glassId, e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public int deleteGlassInfosByEngineeringId(String engineeringId) { |
| | | if (engineeringId == null || engineeringId.trim().isEmpty()) { |
| | | return 0; |
| | | } |
| | | |
| | | try { |
| | | // 先查询要删除的数量(删除前) |
| | | LambdaQueryWrapper<GlassInfo> countWrapper = new LambdaQueryWrapper<>(); |
| | | countWrapper.eq(GlassInfo::getEngineeringId, engineeringId.trim()) |
| | | .eq(GlassInfo::getIsDeleted, 0); // 查询未删除的记录 |
| | | long count = this.count(countWrapper); |
| | | |
| | | // 使用MyBatis-Plus的remove方法,会根据@TableLogic自动进行逻辑删除 |
| | | LambdaQueryWrapper<GlassInfo> removeWrapper = new LambdaQueryWrapper<>(); |
| | | removeWrapper.eq(GlassInfo::getEngineeringId, engineeringId.trim()) |
| | | .eq(GlassInfo::getIsDeleted, 0); // 只删除未删除的记录 |
| | | |
| | | boolean result = this.remove(removeWrapper); |
| | | if (result) { |
| | | log.info("已删除工程号下的玻璃信息: engineeringId={}, count={}", engineeringId, count); |
| | | return (int) count; |
| | | } |
| | | return 0; |
| | | } catch (Exception e) { |
| | | log.error("删除工程号下的玻璃信息失败: engineeringId={}", engineeringId, e); |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | } |
| | | |