huang
6 天以前 9571229a2013472dc701ecf5767f2873b36d8f90
mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/GlassInfoServiceImpl.java
@@ -5,19 +5,17 @@
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.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.math.BigDecimal;
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;
@@ -32,6 +30,9 @@
@RefreshScope
@Service("deviceGlassInfoService")
public class GlassInfoServiceImpl extends ServiceImpl<DeviceGlassInfoMapper, GlassInfo> implements GlassInfoService {
    @Autowired
    private EngineeringSequenceService engineeringSequenceService;
    @Override
    public GlassInfo getGlassInfo(String glassId) {
@@ -230,9 +231,8 @@
            return result;
        }
        // 工程号生成:P + yyMMdd + 序号(2位)
        AtomicInteger seq = new AtomicInteger(1);
        final String engineerId = generateEngineerId(firstValue(excelRows, "glassId"), seq.getAndIncrement());
        // 工程号生成:每次导入都生成新的工程号(使用数据库自增序号,避免重复)
        final String engineerId = engineeringSequenceService.generateAndSaveEngineeringId(new Date());
        final String filmsIdDefault = firstValue(excelRows, "filmsId", "白玻");
        final double thicknessDefault = parseDouble(firstValue(excelRows, "thickness"), 0d);
@@ -243,8 +243,9 @@
        List<Map<String, Object>> glassInfolList = excelRows.stream()
                .flatMap(row -> {
                    int qty = (int) parseDouble(row.getOrDefault("quantity", 1), 1);
                    if (qty <= 0) qty = 1;
                    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);
                    String flowCardId = str(row.get("flowCardId"));
@@ -255,9 +256,15 @@
                    double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal);
                    int finalQty = qty;
                    log.info("解析到数量:row={}, quantity={}, 最终qty={}", row, qtyObj, finalQty);
                    return range(0, qty).mapToObj(idx -> {
                        String finalGlassId = finalQty > 1 ? glassId + "_" + (idx + 1) : glassId;
                        String finalFlowCardId = flowCardId.isEmpty() ? finalGlassId : flowCardId;
                        String baseGlassId = engineerIdFinal + glassId;
                        String finalGlassId = finalQty > 1 ? baseGlassId + "_" + (idx + 1) : baseGlassId;
                        String baseFlowCardId = flowCardId.isEmpty() ? baseGlassId : flowCardId;
                        String finalFlowCardSequence = baseFlowCardId + "/" + (idx + 1);
                        String finalFlowCardId = baseFlowCardId;
                        Map<String, Object> m = new HashMap<>();
                        m.put("xAxis", 0);
                        m.put("xCoordinate", 0);
@@ -288,7 +295,7 @@
                        m.put("combine", 0);
                        m.put("markIcon", "");
                        m.put("filmRemove", 0);
                        m.put("flowCardSequence", flowCardId + "/" + (idx + 1));
                        m.put("flowCardSequence", finalFlowCardSequence);
                        m.put("process", "");
                        m.put("rawAngle", 0);
                        m.put("graphNo", 0);
@@ -389,47 +396,6 @@
        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值(默认空字符串)
@@ -515,5 +481,142 @@
        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> 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 height = parseDouble(row.get("height"), 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(height));
                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;
        }
    }
}