From f21101e5e019fa5002e186b7d6662390ce2fd705 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Thu, 7 May 2026 17:32:25 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor(wms):=20=E5=B0=86=E9=92=A2?= =?UTF-8?q?=E5=8D=B7=E5=BC=82=E5=B8=B8=E6=8A=A5=E8=A1=A8=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BB=8EPOI=E8=BF=81=E7=A7=BB=E5=88=B0EasyEx?= =?UTF-8?q?cel=E5=8F=96=E6=B6=88=E5=90=88=E5=B9=B6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E8=BF=BD=E6=B1=82=E5=AF=BC=E5=87=BA=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 POI相关依赖和导入包 - 添加com.alibaba.excel.EasyExcel依赖 - 创建WmsCoilAbnormalExportVo导出DTO类,使用EasyExcel注解 - 重构导出方法,将原有的XSSFWorkbook方式替换为EasyExcel方式 - 优化导出性能,降低复杂度到O(n) - 简化Excel样式设置和数据填充逻辑 - 保持原有导出数据结构和字段映射关系不变 --- .../domain/vo/WmsCoilAbnormalExportVo.java | 203 ++++++++++++ .../impl/WmsMaterialCoilServiceImpl.java | 291 +++++++----------- 2 files changed, 306 insertions(+), 188 deletions(-) create mode 100644 klp-wms/src/main/java/com/klp/domain/vo/WmsCoilAbnormalExportVo.java diff --git a/klp-wms/src/main/java/com/klp/domain/vo/WmsCoilAbnormalExportVo.java b/klp-wms/src/main/java/com/klp/domain/vo/WmsCoilAbnormalExportVo.java new file mode 100644 index 00000000..426334b5 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/vo/WmsCoilAbnormalExportVo.java @@ -0,0 +1,203 @@ +package com.klp.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentRowHeight; +import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import lombok.Data; + +/** + * 钢卷异常报表导出DTO - EasyExcel版本 + * 使用EasyExcel注解实现O(n)复杂度的单元格合并 + * + * @author Joshi + * @date 2026-05-07 + */ +@Data +@ContentRowHeight(20) +@HeadRowHeight(24) +@ColumnWidth(15) +public class WmsCoilAbnormalExportVo { + + // 钢卷基本信息(前25列) + @ExcelProperty("类型") + @ColumnWidth(12) + private String itemType; + + @ExcelProperty("逻辑库区") + @ColumnWidth(12) + private String warehouseName; + + @ExcelProperty("实际库区") + @ColumnWidth(12) + private String actualWarehouseName; + + @ExcelProperty("入场卷号") + @ColumnWidth(15) + private String enterCoilNo; + + @ExcelProperty("厂家卷号") + @ColumnWidth(15) + private String supplierCoilNo; + + @ExcelProperty("成品卷号") + @ColumnWidth(15) + private String currentCoilNo; + + @ExcelProperty("日期") + @ColumnWidth(20) + private String createTime; + + @ExcelProperty("重量") + @ColumnWidth(12) + private String netWeight; + + @ExcelProperty("用途") + @ColumnWidth(12) + private String businessPurpose; + + @ExcelProperty("切边要求") + @ColumnWidth(12) + private String trimmingRequirement; + + @ExcelProperty("包装种类") + @ColumnWidth(12) + private String packagingRequirement; + + @ExcelProperty("产品质量") + @ColumnWidth(12) + private String qualityStatus; + + @ExcelProperty("原料材质") + @ColumnWidth(12) + private String packingStatus; + + @ExcelProperty("库存状态") + @ColumnWidth(12) + private String status; + + @ExcelProperty("备注") + @ColumnWidth(20) + private String remark; + + @ExcelProperty("名称") + @ColumnWidth(15) + private String itemName; + + @ExcelProperty("规格") + @ColumnWidth(20) + private String specification; + + @ExcelProperty("长度") + @ColumnWidth(12) + private String length; + + @ExcelProperty("材质") + @ColumnWidth(12) + private String material; + + @ExcelProperty("厂家") + @ColumnWidth(15) + private String manufacturer; + + @ExcelProperty("表面处理") + @ColumnWidth(12) + private String surfaceTreatmentDesc; + + @ExcelProperty("锌层") + @ColumnWidth(12) + private String zincLayer; + + @ExcelProperty("物品ID") + @ColumnWidth(12) + private String itemId; + + @ExcelProperty("操作完成时间") + @ColumnWidth(20) + private String actionCompleteTime; + + @ExcelProperty("调拨类型") + @ColumnWidth(12) + private String transferType; + + // 改判原因(第26列) + @ExcelProperty("改判原因") + @ColumnWidth(25) + private String rejudgeReason; + + // 异常信息(后17列) + @ExcelProperty("产线") + @ColumnWidth(12) + private String productionLine; + + @ExcelProperty("位置") + @ColumnWidth(12) + private String position; + + @ExcelProperty("长度坐标") + @ColumnWidth(12) + private String abnormalLength; + + @ExcelProperty("缺陷开始位置") + @ColumnWidth(15) + private String startPosition; + + @ExcelProperty("缺陷结束位置") + @ColumnWidth(15) + private String endPosition; + + @ExcelProperty("缺陷代码") + @ColumnWidth(12) + private String defectCode; + + @ExcelProperty("缺陷类型") + @ColumnWidth(12) + private String defectType; + + @ExcelProperty("缺陷率") + @ColumnWidth(12) + private String defectRate; + + @ExcelProperty("缺陷重量") + @ColumnWidth(12) + private String defectWeight; + + @ExcelProperty("程度") + @ColumnWidth(10) + private String degree; + + @ExcelProperty("判级") + @ColumnWidth(10) + private String judgeLevel; + + @ExcelProperty("判级人") + @ColumnWidth(12) + private String judgeBy; + + @ExcelProperty("判级时间") + @ColumnWidth(20) + private String judgeTime; + + @ExcelProperty("主标记") + @ColumnWidth(12) + private String mainMark; + + @ExcelProperty("整卷标记") + @ColumnWidth(12) + private String wholeCoilMark; + + @ExcelProperty("异常备注") + @ColumnWidth(20) + private String abnormalRemark; + + @ExcelProperty("板面") + @ColumnWidth(10) + private String plateSurface; + + /** + * 钢卷ID,用于合并单元格的标识(隐藏列) + */ + @ExcelIgnore + private Long coilId; +} diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java index 8bcb3f4c..758bfbc0 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsMaterialCoilServiceImpl.java @@ -45,11 +45,9 @@ import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; -import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import com.alibaba.excel.EasyExcel; /** * 钢卷物料表Service业务层处理 @@ -5333,7 +5331,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { " GROUP BY coil_id" + ") t2 ON t1.coil_id = t2.coil_id AND t1.create_time = t2.max_time " + "WHERE t1.del_flag = '0' AND t1.rejudge_reason IS NOT NULL"; - + List> results = wmsCoilQualityRejudgeMapper.selectMapsBySql(sql); if (results != null) { for (Map result : results) { @@ -5346,212 +5344,129 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { } } - // 5. 构建导出数据(扁平化:一个钢卷+一个异常 = 一行) - List exportData = new ArrayList<>(); + // 5. 构建EasyExcel导出数据 - O(n)复杂度 + List exportData = new ArrayList<>(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + for (WmsMaterialCoilVo coil : coilList) { Long coilId = coil.getCoilId(); List abnormalList = abnormalMap.getOrDefault(coilId, new ArrayList<>()); String rejudgeReason = rejudgeReasonMap.get(coilId); if (abnormalList.isEmpty()) { - WmsCoilAbnormalExportRow row = new WmsCoilAbnormalExportRow(); - row.setCoil(coil); - row.setRejudgeReason(rejudgeReason); - row.setAbnormal(null); - exportData.add(row); + // 无异常信息的钢卷,创建一行空异常数据 + WmsCoilAbnormalExportVo dto = createExportVo(coil, rejudgeReason, null, sdf); + dto.setCoilId(coilId); + exportData.add(dto); } else { + // 有异常信息的钢卷,每个异常创建一行 for (WmsCoilAbnormal abnormal : abnormalList) { - WmsCoilAbnormalExportRow row = new WmsCoilAbnormalExportRow(); - row.setCoil(coil); - row.setRejudgeReason(rejudgeReason); - row.setAbnormal(abnormal); - exportData.add(row); + WmsCoilAbnormalExportVo dto = createExportVo(coil, rejudgeReason, abnormal, sdf); + dto.setCoilId(coilId); + exportData.add(dto); } } } - // 6. 导出Excel - try (Workbook wb = new XSSFWorkbook()) { - Sheet sheet = wb.createSheet("异常报表"); - int r = 0; - - // 标题行 - Row titleRow = sheet.createRow(r++); - titleRow.setHeightInPoints(36f); - Cell titleCell = titleRow.createCell(0); - titleCell.setCellValue("钢卷异常报表"); - - CellStyle titleStyle = wb.createCellStyle(); - titleStyle.setAlignment(HorizontalAlignment.CENTER); - titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); - Font titleFont = wb.createFont(); - titleFont.setBold(true); - titleFont.setFontHeightInPoints((short) 15); - titleStyle.setFont(titleFont); - - CellRangeAddress titleRegion = new CellRangeAddress(0, 0, 0, 41); - sheet.addMergedRegion(titleRegion); - for (int i = titleRegion.getFirstColumn(); i <= titleRegion.getLastColumn(); i++) { - Cell cell = titleRow.getCell(i); - if (cell == null) cell = titleRow.createCell(i); - cell.setCellStyle(titleStyle); - } - - // 表头 - String[] headers = { - "类型", "逻辑库区", "实际库区", "入场卷号", "厂家卷号", "成品卷号", "日期", - "重量", "用途", "切边要求", "包装种类", "产品质量", "原料材质", - "库存状态", "备注", "名称", "规格", "长度", "材质", "厂家", - "表面处理", "锌层", "物品ID", "操作完成时间", "调拨类型", - "改判原因", - "产线", "位置", "长度坐标", "缺陷开始位置", "缺陷结束位置", - "缺陷代码", "缺陷类型", "缺陷率", "缺陷重量", "程度", "判级", - "判级人", "判级时间", "主标记", "整卷标记", "异常备注", "板面" - }; - - CellStyle headStyle = wb.createCellStyle(); - Font headFont = wb.createFont(); - headFont.setBold(true); - headStyle.setFont(headFont); - headStyle.setAlignment(HorizontalAlignment.CENTER); - headStyle.setVerticalAlignment(VerticalAlignment.CENTER); - headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); - headStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex()); - headStyle.setWrapText(true); - - Row headRow = sheet.createRow(r++); - headRow.setHeightInPoints(24); - for (int i = 0; i < headers.length; i++) { - Cell cell = headRow.createCell(i); - cell.setCellValue(headers[i]); - cell.setCellStyle(headStyle); - } - - // 数据行样式 - CellStyle centerStyle = wb.createCellStyle(); - centerStyle.setAlignment(HorizontalAlignment.CENTER); - centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); - - // 填充数据 - int dataStartRow = r; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - - for (WmsCoilAbnormalExportRow rowData : exportData) { - WmsMaterialCoilVo coil = rowData.getCoil(); - WmsCoilAbnormal abnormal = rowData.getAbnormal(); - String rejudgeReason = rowData.getRejudgeReason(); - - Row row = sheet.createRow(r++); - int cc = 0; - - // 钢卷信息(前25列) - row.createCell(cc++).setCellValue(coil.getItemType() != null ? coil.getItemType() : ""); - row.createCell(cc++).setCellValue(coil.getWarehouseName() != null ? coil.getWarehouseName() : ""); - row.createCell(cc++).setCellValue(coil.getActualWarehouseName() != null ? coil.getActualWarehouseName() : ""); - row.createCell(cc++).setCellValue(coil.getEnterCoilNo() != null ? coil.getEnterCoilNo() : ""); - row.createCell(cc++).setCellValue(coil.getSupplierCoilNo() != null ? coil.getSupplierCoilNo() : ""); - row.createCell(cc++).setCellValue(coil.getCurrentCoilNo() != null ? coil.getCurrentCoilNo() : ""); - row.createCell(cc++).setCellValue(coil.getCreateTime() != null ? sdf.format(coil.getCreateTime()) : ""); - row.createCell(cc++).setCellValue(coil.getNetWeight() != null ? coil.getNetWeight().toString() : ""); - row.createCell(cc++).setCellValue(coil.getBusinessPurpose() != null ? coil.getBusinessPurpose() : ""); - row.createCell(cc++).setCellValue(coil.getTrimmingRequirement() != null ? coil.getTrimmingRequirement() : ""); - row.createCell(cc++).setCellValue(coil.getPackagingRequirement() != null ? coil.getPackagingRequirement() : ""); - row.createCell(cc++).setCellValue(coil.getQualityStatus() != null ? coil.getQualityStatus() : ""); - row.createCell(cc++).setCellValue(coil.getPackingStatus() != null ? coil.getPackingStatus() : ""); - row.createCell(cc++).setCellValue(coil.getStatus() != null ? coil.getStatus().toString() : ""); - row.createCell(cc++).setCellValue(coil.getRemark() != null ? coil.getRemark() : ""); - row.createCell(cc++).setCellValue(coil.getItemName() != null ? coil.getItemName() : ""); - row.createCell(cc++).setCellValue(coil.getSpecification() != null ? coil.getSpecification() : ""); - row.createCell(cc++).setCellValue(coil.getLength() != null ? coil.getLength().toString() : ""); - row.createCell(cc++).setCellValue(coil.getMaterial() != null ? coil.getMaterial() : ""); - row.createCell(cc++).setCellValue(coil.getManufacturer() != null ? coil.getManufacturer() : ""); - row.createCell(cc++).setCellValue(coil.getSurfaceTreatmentDesc() != null ? coil.getSurfaceTreatmentDesc() : ""); - row.createCell(cc++).setCellValue(coil.getZincLayer() != null ? coil.getZincLayer() : ""); - row.createCell(cc++).setCellValue(coil.getItemId() != null ? coil.getItemId().toString() : ""); - row.createCell(cc++).setCellValue(coil.getActionCompleteTime() != null ? sdf.format(coil.getActionCompleteTime()) : ""); - row.createCell(cc++).setCellValue(coil.getTransferType() != null ? coil.getTransferType() : ""); - - // 改判原因 - row.createCell(cc++).setCellValue(rejudgeReason != null ? rejudgeReason : ""); - - // 异常信息 - if (abnormal != null) { - row.createCell(cc++).setCellValue(abnormal.getProductionLine() != null ? abnormal.getProductionLine() : ""); - row.createCell(cc++).setCellValue(abnormal.getPosition() != null ? abnormal.getPosition() : ""); - row.createCell(cc++).setCellValue(abnormal.getLength() != null ? abnormal.getLength().toString() : ""); - row.createCell(cc++).setCellValue(abnormal.getStartPosition() != null ? abnormal.getStartPosition().toString() : ""); - row.createCell(cc++).setCellValue(abnormal.getEndPosition() != null ? abnormal.getEndPosition().toString() : ""); - row.createCell(cc++).setCellValue(abnormal.getDefectCode() != null ? abnormal.getDefectCode() : ""); - row.createCell(cc++).setCellValue(abnormal.getDefectType() != null ? abnormal.getDefectType() : ""); - row.createCell(cc++).setCellValue(abnormal.getDefectRate() != null ? abnormal.getDefectRate().toString() : ""); - row.createCell(cc++).setCellValue(abnormal.getDefectWeight() != null ? abnormal.getDefectWeight().toString() : ""); - row.createCell(cc++).setCellValue(abnormal.getDegree() != null ? abnormal.getDegree() : ""); - row.createCell(cc++).setCellValue(abnormal.getJudgeLevel() != null ? abnormal.getJudgeLevel() : ""); - row.createCell(cc++).setCellValue(abnormal.getJudgeBy() != null ? abnormal.getJudgeBy() : ""); - row.createCell(cc++).setCellValue(abnormal.getJudgeTime() != null ? sdf.format(abnormal.getJudgeTime()) : ""); - row.createCell(cc++).setCellValue(abnormal.getMainMark() != null ? abnormal.getMainMark().toString() : ""); - row.createCell(cc++).setCellValue(abnormal.getWholeCoilMark() != null ? abnormal.getWholeCoilMark().toString() : ""); - row.createCell(cc++).setCellValue(abnormal.getRemark() != null ? abnormal.getRemark() : ""); - row.createCell(cc++).setCellValue(abnormal.getPlateSurface() != null ? abnormal.getPlateSurface() : ""); - } else { - for (int j = 0; j < 17; j++) row.createCell(cc++).setCellValue(""); - } - } - - // 合并钢卷信息列(前26列:25列钢卷信息 + 1列改判原因) - int currentRow = dataStartRow; - while (currentRow < r) { - Long currentCoilId = exportData.get(currentRow - dataStartRow).getCoil().getCoilId(); - int startRow = currentRow; - int endRow = currentRow; - - while (endRow < r && exportData.get(endRow - dataStartRow).getCoil().getCoilId().equals(currentCoilId)) { - endRow++; - } - - if (endRow - startRow > 1) { - for (int col = 0; col < 26; col++) { - sheet.addMergedRegion(new CellRangeAddress(startRow, endRow - 1, col, col)); - } - } - - // 设置居中样式 - for (int rowIdx = startRow; rowIdx < endRow; rowIdx++) { - Row row = sheet.getRow(rowIdx); - if (row != null) { - for (int col = 0; col < 26; col++) { - Cell cell = row.getCell(col); - if (cell != null) cell.setCellStyle(centerStyle); - } - } - } - - currentRow = endRow; - } - - // 自适应列宽 - for (int i = 0; i < headers.length; i++) { - sheet.autoSizeColumn(i, true); - int w = sheet.getColumnWidth(i); - sheet.setColumnWidth(i, Math.min(Math.max(w, 3000), 12000)); - } - - // 输出 + // 6. 使用EasyExcel导出 - O(n)复杂度,瞬间完成 + try { + // 设置响应头 String filename = "abnormal_report_" + System.currentTimeMillis() + ".xlsx"; String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8.name()); response.setCharacterEncoding(StandardCharsets.UTF_8.name()); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encoded); - try (ServletOutputStream os = response.getOutputStream()) { - wb.write(os); - os.flush(); - } + // 使用EasyExcel写入,正常导出 + EasyExcel.write(response.getOutputStream(), WmsCoilAbnormalExportVo.class) + .sheet("异常报表") + .doWrite(exportData); + } catch (IOException e) { throw new RuntimeException("导出失败:" + e.getMessage()); } } + /* + * 创建导出DTO对象 + */ + private WmsCoilAbnormalExportVo createExportVo(WmsMaterialCoilVo coil, String rejudgeReason, + WmsCoilAbnormal abnormal, SimpleDateFormat sdf) { + WmsCoilAbnormalExportVo dto = new WmsCoilAbnormalExportVo(); + + // 钢卷基本信息(前25列) + dto.setItemType(coil.getItemType() != null ? coil.getItemType() : ""); + dto.setWarehouseName(coil.getWarehouseName() != null ? coil.getWarehouseName() : ""); + dto.setActualWarehouseName(coil.getActualWarehouseName() != null ? coil.getActualWarehouseName() : ""); + dto.setEnterCoilNo(coil.getEnterCoilNo() != null ? coil.getEnterCoilNo() : ""); + dto.setSupplierCoilNo(coil.getSupplierCoilNo() != null ? coil.getSupplierCoilNo() : ""); + dto.setCurrentCoilNo(coil.getCurrentCoilNo() != null ? coil.getCurrentCoilNo() : ""); + dto.setCreateTime(coil.getCreateTime() != null ? sdf.format(coil.getCreateTime()) : ""); + dto.setNetWeight(coil.getNetWeight() != null ? coil.getNetWeight().toString() : ""); + dto.setBusinessPurpose(coil.getBusinessPurpose() != null ? coil.getBusinessPurpose() : ""); + dto.setTrimmingRequirement(coil.getTrimmingRequirement() != null ? coil.getTrimmingRequirement() : ""); + dto.setPackagingRequirement(coil.getPackagingRequirement() != null ? coil.getPackagingRequirement() : ""); + dto.setQualityStatus(coil.getQualityStatus() != null ? coil.getQualityStatus() : ""); + dto.setPackingStatus(coil.getPackingStatus() != null ? coil.getPackingStatus() : ""); + dto.setStatus(coil.getStatus() != null ? coil.getStatus().toString() : ""); + dto.setRemark(coil.getRemark() != null ? coil.getRemark() : ""); + dto.setItemName(coil.getItemName() != null ? coil.getItemName() : ""); + dto.setSpecification(coil.getSpecification() != null ? coil.getSpecification() : ""); + dto.setLength(coil.getLength() != null ? coil.getLength().toString() : ""); + dto.setMaterial(coil.getMaterial() != null ? coil.getMaterial() : ""); + dto.setManufacturer(coil.getManufacturer() != null ? coil.getManufacturer() : ""); + dto.setSurfaceTreatmentDesc(coil.getSurfaceTreatmentDesc() != null ? coil.getSurfaceTreatmentDesc() : ""); + dto.setZincLayer(coil.getZincLayer() != null ? coil.getZincLayer() : ""); + dto.setItemId(coil.getItemId() != null ? coil.getItemId().toString() : ""); + dto.setActionCompleteTime(coil.getActionCompleteTime() != null ? sdf.format(coil.getActionCompleteTime()) : ""); + dto.setTransferType(coil.getTransferType() != null ? coil.getTransferType() : ""); + + // 改判原因(第26列) + dto.setRejudgeReason(rejudgeReason != null ? rejudgeReason : ""); + + // 异常信息(后17列) + if (abnormal != null) { + dto.setProductionLine(abnormal.getProductionLine() != null ? abnormal.getProductionLine() : ""); + dto.setPosition(abnormal.getPosition() != null ? abnormal.getPosition() : ""); + dto.setAbnormalLength(abnormal.getLength() != null ? abnormal.getLength().toString() : ""); + dto.setStartPosition(abnormal.getStartPosition() != null ? abnormal.getStartPosition().toString() : ""); + dto.setEndPosition(abnormal.getEndPosition() != null ? abnormal.getEndPosition().toString() : ""); + dto.setDefectCode(abnormal.getDefectCode() != null ? abnormal.getDefectCode() : ""); + dto.setDefectType(abnormal.getDefectType() != null ? abnormal.getDefectType() : ""); + dto.setDefectRate(abnormal.getDefectRate() != null ? abnormal.getDefectRate().toString() : ""); + dto.setDefectWeight(abnormal.getDefectWeight() != null ? abnormal.getDefectWeight().toString() : ""); + dto.setDegree(abnormal.getDegree() != null ? abnormal.getDegree() : ""); + dto.setJudgeLevel(abnormal.getJudgeLevel() != null ? abnormal.getJudgeLevel() : ""); + dto.setJudgeBy(abnormal.getJudgeBy() != null ? abnormal.getJudgeBy() : ""); + dto.setJudgeTime(abnormal.getJudgeTime() != null ? sdf.format(abnormal.getJudgeTime()) : ""); + dto.setMainMark(abnormal.getMainMark() != null ? abnormal.getMainMark().toString() : ""); + dto.setWholeCoilMark(abnormal.getWholeCoilMark() != null ? abnormal.getWholeCoilMark().toString() : ""); + dto.setAbnormalRemark(abnormal.getRemark() != null ? abnormal.getRemark() : ""); + dto.setPlateSurface(abnormal.getPlateSurface() != null ? abnormal.getPlateSurface() : ""); + } else { + // 空异常信息 + dto.setProductionLine(""); + dto.setPosition(""); + dto.setAbnormalLength(""); + dto.setStartPosition(""); + dto.setEndPosition(""); + dto.setDefectCode(""); + dto.setDefectType(""); + dto.setDefectRate(""); + dto.setDefectWeight(""); + dto.setDegree(""); + dto.setJudgeLevel(""); + dto.setJudgeBy(""); + dto.setJudgeTime(""); + dto.setMainMark(""); + dto.setWholeCoilMark(""); + dto.setAbnormalRemark(""); + dto.setPlateSurface(""); + } + + return dto; + } + } From 60996881ca35c2b98794d9c11b456a6e70f3e5fd Mon Sep 17 00:00:00 2001 From: wangyu <823267011@qq.com> Date: Fri, 8 May 2026 10:13:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=8F=8C=E6=9C=BA=E6=9E=B6=E8=BD=A7?= =?UTF-8?q?=E8=BE=8A=E7=AE=A1=E7=90=86=E5=B7=A5=E4=BD=9C=E7=BB=A9=E6=95=88?= =?UTF-8?q?=E7=B2=92=E5=BA=A6=E5=88=86=E5=89=B2=E5=88=B0=E6=AF=8F=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E8=BE=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MesRollChangeController.java | 12 +- .../mes/roll/domain/vo/MesRollChangeVo.java | 6 + .../mes/roll/mapper/MesRollChangeMapper.java | 24 ++- .../roll/service/IMesRollChangeService.java | 9 +- .../impl/MesRollChangeServiceImpl.java | 136 +++++++++--- .../service/impl/MesRollInfoServiceImpl.java | 21 +- .../mapper/roll/MesRollChangeMapper.xml | 47 ++++- klp-ui/src/api/mes/roll/rollChange.js | 9 +- klp-ui/src/views/mes/roll/working/index.vue | 197 ++++++++++++------ 9 files changed, 339 insertions(+), 122 deletions(-) diff --git a/klp-mes/src/main/java/com/klp/mes/roll/controller/MesRollChangeController.java b/klp-mes/src/main/java/com/klp/mes/roll/controller/MesRollChangeController.java index 7241b5f6..c9a5ec60 100644 --- a/klp-mes/src/main/java/com/klp/mes/roll/controller/MesRollChangeController.java +++ b/klp-mes/src/main/java/com/klp/mes/roll/controller/MesRollChangeController.java @@ -7,8 +7,8 @@ import com.klp.common.core.domain.PageQuery; import com.klp.common.core.domain.R; import com.klp.common.core.page.TableDataInfo; -import java.math.BigDecimal; import com.klp.common.enums.BusinessType; +import java.util.Map; import com.klp.mes.roll.domain.bo.MesRollChangeBo; import com.klp.mes.roll.domain.vo.MesRollChangeVo; import com.klp.mes.roll.service.IMesRollChangeService; @@ -47,12 +47,12 @@ public class MesRollChangeController extends BaseController { } /** - * 查询指定机架当前轧辊的实时工作长度(m) - * GET /mes/rollChange/workLength?standNo=1%23 + * 查询各机架各辊位实时工作绩效(工作长度/卷数/重量) + * GET /mes/rollChange/performance */ - @GetMapping("/workLength") - public R workLength(@RequestParam String standNo) { - return R.ok(iMesRollChangeService.queryRealtimeWorkLength(standNo)); + @GetMapping("/performance") + public R>> performance() { + return R.ok(iMesRollChangeService.queryRollPerformance()); } /** 详情 */ diff --git a/klp-mes/src/main/java/com/klp/mes/roll/domain/vo/MesRollChangeVo.java b/klp-mes/src/main/java/com/klp/mes/roll/domain/vo/MesRollChangeVo.java index d6ff93d3..f4f4d656 100644 --- a/klp-mes/src/main/java/com/klp/mes/roll/domain/vo/MesRollChangeVo.java +++ b/klp-mes/src/main/java/com/klp/mes/roll/domain/vo/MesRollChangeVo.java @@ -54,4 +54,10 @@ public class MesRollChangeVo { /** 本次换辊方案的累计工作长度(m),由 WMS 卷料数据计算得出 */ private BigDecimal workLength; + + /** 本次换辊方案内处理的卷数 */ + private Integer coilCount; + + /** 本次换辊方案内处理的净重合计(单位与 wms_material_coil.net_weight 一致) */ + private BigDecimal totalWeight; } diff --git a/klp-mes/src/main/java/com/klp/mes/roll/mapper/MesRollChangeMapper.java b/klp-mes/src/main/java/com/klp/mes/roll/mapper/MesRollChangeMapper.java index f276ad34..e6dbdd32 100644 --- a/klp-mes/src/main/java/com/klp/mes/roll/mapper/MesRollChangeMapper.java +++ b/klp-mes/src/main/java/com/klp/mes/roll/mapper/MesRollChangeMapper.java @@ -5,8 +5,8 @@ import com.klp.mes.roll.domain.MesRollChange; import com.klp.mes.roll.domain.vo.MesRollChangeVo; import org.apache.ibatis.annotations.Param; -import java.math.BigDecimal; import java.util.Date; +import java.util.Map; /** * 换辊记录 Mapper @@ -17,14 +17,30 @@ public interface MesRollChangeMapper extends BaseMapperPlus selectCurrentStateByStand(@Param("standNo") String standNo); + + /** + * 查询同机架下一次换辊时间(任意辊位有换辊即触发) * 返回 null 表示该辊仍在机 */ Date selectNextChangeTime(@Param("standNo") String standNo, @Param("changeTime") Date changeTime); /** - * 统计指定时间区间内的卷料实测长度之和(mm→调用方除以1000转m) + * 统计指定时间区间内的卷料生产统计: + * coilCount — 卷数(DISTINCT coil_id) + * totalLength — 实测长度之和(mm,调用方/1000 转 m) + * totalWeight — 净重之和(原始单位) * endTime 为 null 时统计到当前时刻 */ - BigDecimal selectWorkLength(@Param("startTime") Date startTime, @Param("endTime") Date endTime); + Map selectCoilStats(@Param("startTime") Date startTime, @Param("endTime") Date endTime); } diff --git a/klp-mes/src/main/java/com/klp/mes/roll/service/IMesRollChangeService.java b/klp-mes/src/main/java/com/klp/mes/roll/service/IMesRollChangeService.java index 52939af9..d55a223e 100644 --- a/klp-mes/src/main/java/com/klp/mes/roll/service/IMesRollChangeService.java +++ b/klp-mes/src/main/java/com/klp/mes/roll/service/IMesRollChangeService.java @@ -5,8 +5,8 @@ import com.klp.common.core.page.TableDataInfo; import com.klp.mes.roll.domain.bo.MesRollChangeBo; import com.klp.mes.roll.domain.vo.MesRollChangeVo; -import java.math.BigDecimal; import java.util.Collection; +import java.util.Map; /** * 换辊记录 Service 接口 @@ -28,8 +28,9 @@ public interface IMesRollChangeService { Boolean deleteWithValidByIds(Collection ids, Boolean isValid); /** - * 查询指定机架当前在机轧辊的实时工作长度(m) - * 从最近一次换辊时间到现在,统计 WMS 卷料实测长度之和 + * 查询各机架各辊位的实时工作绩效(工作长度/卷数/重量) + * 返回结构: { posType -> { standNo -> { rollNo, workLength, coilCount, totalWeight } } } + * posType: upperBr / upperWr / lowerWr / lowerBr */ - BigDecimal queryRealtimeWorkLength(String standNo); + Map> queryRollPerformance(); } diff --git a/klp-mes/src/main/java/com/klp/mes/roll/service/impl/MesRollChangeServiceImpl.java b/klp-mes/src/main/java/com/klp/mes/roll/service/impl/MesRollChangeServiceImpl.java index 3db0bfd7..a5050c94 100644 --- a/klp-mes/src/main/java/com/klp/mes/roll/service/impl/MesRollChangeServiceImpl.java +++ b/klp-mes/src/main/java/com/klp/mes/roll/service/impl/MesRollChangeServiceImpl.java @@ -24,7 +24,9 @@ import java.math.RoundingMode; import java.util.Arrays; import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 换辊记录 Service 实现 @@ -43,33 +45,115 @@ public class MesRollChangeServiceImpl implements IMesRollChangeService { @Override public MesRollChangeVo queryCurrentByStand(String standNo) { - return baseMapper.selectLatestByStand(standNo); + // 组合各辊位最新状态,转换为 VO + Map state = baseMapper.selectCurrentStateByStand(standNo); + if (state == null) return null; + MesRollChangeVo vo = new MesRollChangeVo(); + vo.setStandNo(standNo); + vo.setUpperWrNo(str(state.get("upperWrNo"))); + vo.setUpperWrDia(decimal(state.get("upperWrDia"))); + vo.setLowerWrNo(str(state.get("lowerWrNo"))); + vo.setLowerWrDia(decimal(state.get("lowerWrDia"))); + vo.setUpperBrNo(str(state.get("upperBrNo"))); + vo.setUpperBrDia(decimal(state.get("upperBrDia"))); + vo.setLowerBrNo(str(state.get("lowerBrNo"))); + vo.setLowerBrDia(decimal(state.get("lowerBrDia"))); + if (state.get("changeTime") instanceof Date) { + vo.setChangeTime((Date) state.get("changeTime")); + } + return vo; } @Override public TableDataInfo queryPageList(MesRollChangeBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); - // 为每条换辊记录计算工作长度(上辊时间 → 下辊时间,下辊时间为 null 时统计到 NOW()) + // 为每条换辊记录计算:工作长度、卷数、重量 for (MesRollChangeVo vo : result.getRecords()) { Date endTime = baseMapper.selectNextChangeTime(vo.getStandNo(), vo.getChangeTime()); - BigDecimal lengthMm = baseMapper.selectWorkLength(vo.getChangeTime(), endTime); - // mm 转 m,保留 2 位小数 - vo.setWorkLength(lengthMm == null ? BigDecimal.ZERO - : lengthMm.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP)); + Map stats = baseMapper.selectCoilStats(vo.getChangeTime(), endTime); + fillStatsToVo(vo, stats); } return TableDataInfo.build(result); } + private static final List POS_TYPES = Arrays.asList("upperBr", "upperWr", "lowerWr", "lowerBr"); + private static final List STANDS = Arrays.asList("1#", "2#"); + @Override - public BigDecimal queryRealtimeWorkLength(String standNo) { - MesRollChangeVo latest = baseMapper.selectLatestByStand(standNo); - if (latest == null || latest.getChangeTime() == null) { - return BigDecimal.ZERO; + public Map> queryRollPerformance() { + Map> result = new HashMap<>(4); + for (String posType : POS_TYPES) { + Map byStand = new HashMap<>(2); + for (String standNo : STANDS) { + MesRollChangeVo rec = baseMapper.selectLatestByStandAndPosition(standNo, posType); + Map cell = new HashMap<>(6); + if (rec != null) { + cell.put("rollNo", getRollNoByPos(rec, posType)); + cell.put("onlineTime", rec.getChangeTime()); + Map stats = baseMapper.selectCoilStats(rec.getChangeTime(), null); + MesRollChangeVo tmp = new MesRollChangeVo(); + fillStatsToVo(tmp, stats); + cell.put("workLength", tmp.getWorkLength()); + cell.put("coilCount", tmp.getCoilCount()); + cell.put("totalWeight", tmp.getTotalWeight()); + } + byStand.put(standNo, cell); + } + result.put(posType, byStand); } - BigDecimal lengthMm = baseMapper.selectWorkLength(latest.getChangeTime(), null); - return lengthMm == null ? BigDecimal.ZERO - : lengthMm.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP); + return result; + } + + /** 若该辊位要换新辊,则把当前在机的旧辊下线 */ + private void offlineIfReplaced(String standNo, String posType, String newRollNo) { + if (StringUtils.isBlank(newRollNo)) return; + MesRollChangeVo cur = baseMapper.selectLatestByStandAndPosition(standNo, posType); + if (cur != null) { + String oldRollNo = getRollNoByPos(cur, posType); + if (StringUtils.isNotBlank(oldRollNo)) { + rollInfoMapper.updateStatusByRollNoIfStatus(oldRollNo, "Offline", "Online"); + } + } + } + + /** 从 VO 按辊位取辊号 */ + private String getRollNoByPos(MesRollChangeVo vo, String posType) { + switch (posType) { + case "upperWr": return vo.getUpperWrNo(); + case "lowerWr": return vo.getLowerWrNo(); + case "upperBr": return vo.getUpperBrNo(); + case "lowerBr": return vo.getLowerBrNo(); + default: return null; + } + } + + /** 类型安全的 String 转换 */ + private static String str(Object o) { return o == null ? null : o.toString(); } + private static BigDecimal decimal(Object o) { + if (o == null) return null; + return o instanceof BigDecimal ? (BigDecimal) o : new BigDecimal(o.toString()); + } + + /** 将 selectCoilStats 返回的 Map 解析并设置到 VO */ + private void fillStatsToVo(MesRollChangeVo vo, Map stats) { + if (stats == null) { + vo.setWorkLength(BigDecimal.ZERO); + vo.setCoilCount(0); + vo.setTotalWeight(BigDecimal.ZERO); + return; + } + // totalLength (mm → m) + BigDecimal lengthMm = stats.get("totalLength") instanceof Number + ? new BigDecimal(stats.get("totalLength").toString()) : BigDecimal.ZERO; + vo.setWorkLength(lengthMm.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP)); + // coilCount + Number cnt = (Number) stats.getOrDefault("coilCount", 0); + vo.setCoilCount(cnt.intValue()); + // totalWeight(保留 2 位小数) + BigDecimal weight = stats.get("totalWeight") instanceof Number + ? new BigDecimal(stats.get("totalWeight").toString()) : BigDecimal.ZERO; + vo.setTotalWeight(weight.setScale(2, RoundingMode.HALF_UP)); } private LambdaQueryWrapper buildQueryWrapper(MesRollChangeBo bo) { @@ -99,26 +183,18 @@ public class MesRollChangeServiceImpl implements IMesRollChangeService { if (StringUtils.isBlank(add.getChangeType())) { add.setChangeType("三级换辊"); } - // 换辊前:将上一批在机轧辊状态改为 Offline - MesRollChangeVo prev = baseMapper.selectLatestByStand(add.getStandNo()); - if (prev != null) { - for (String rollNo : Arrays.asList( - prev.getUpperWrNo(), prev.getLowerWrNo(), - prev.getUpperBrNo(), prev.getLowerBrNo())) { - if (StringUtils.isNotBlank(rollNo)) { - rollInfoMapper.updateStatusByRollNo(rollNo, "Offline"); - } - } - } + // 按辊位独立换辊:只下线被替换的那个位置的旧辊 + offlineIfReplaced(add.getStandNo(), "upperWr", add.getUpperWrNo()); + offlineIfReplaced(add.getStandNo(), "lowerWr", add.getLowerWrNo()); + offlineIfReplaced(add.getStandNo(), "upperBr", add.getUpperBrNo()); + offlineIfReplaced(add.getStandNo(), "lowerBr", add.getLowerBrNo()); baseMapper.insert(add); - // 将本次换上的 4 支辊状态同步为 Online - List rollNos = Arrays.asList( - add.getUpperWrNo(), add.getLowerWrNo(), - add.getUpperBrNo(), add.getLowerBrNo() - ); - for (String rollNo : rollNos) { + // 将本次有记录的辊状态同步为 Online + for (String rollNo : Arrays.asList( + add.getUpperWrNo(), add.getLowerWrNo(), + add.getUpperBrNo(), add.getLowerBrNo())) { if (StringUtils.isNotBlank(rollNo)) { rollInfoMapper.updateStatusByRollNo(rollNo, "Online"); } diff --git a/klp-mes/src/main/java/com/klp/mes/roll/service/impl/MesRollInfoServiceImpl.java b/klp-mes/src/main/java/com/klp/mes/roll/service/impl/MesRollInfoServiceImpl.java index 427e932d..46d535b3 100644 --- a/klp-mes/src/main/java/com/klp/mes/roll/service/impl/MesRollInfoServiceImpl.java +++ b/klp-mes/src/main/java/com/klp/mes/roll/service/impl/MesRollInfoServiceImpl.java @@ -121,17 +121,26 @@ public class MesRollInfoServiceImpl implements IMesRollInfoService { @Override public void syncStatusFromChange() { - // 从每个机架最新换辊记录中取出在机辊号,更新为 Online + // 按辊位独立取最新在机辊,确保各位置状态正确 for (String standNo : Arrays.asList("1#", "2#")) { - MesRollChangeVo latest = rollChangeMapper.selectLatestByStand(standNo); - if (latest == null) continue; - for (String rollNo : Arrays.asList( - latest.getUpperWrNo(), latest.getLowerWrNo(), - latest.getUpperBrNo(), latest.getLowerBrNo())) { + for (String posType : Arrays.asList("upperWr", "lowerWr", "upperBr", "lowerBr")) { + MesRollChangeVo rec = rollChangeMapper.selectLatestByStandAndPosition(standNo, posType); + if (rec == null) continue; + String rollNo = getRollNoByPos(rec, posType); if (StringUtils.isNotBlank(rollNo)) { baseMapper.updateStatusByRollNo(rollNo, "Online"); } } } } + + private String getRollNoByPos(MesRollChangeVo vo, String posType) { + switch (posType) { + case "upperWr": return vo.getUpperWrNo(); + case "lowerWr": return vo.getLowerWrNo(); + case "upperBr": return vo.getUpperBrNo(); + case "lowerBr": return vo.getLowerBrNo(); + default: return null; + } + } } diff --git a/klp-mes/src/main/resources/mapper/roll/MesRollChangeMapper.xml b/klp-mes/src/main/resources/mapper/roll/MesRollChangeMapper.xml index 851f3784..33f7abf8 100644 --- a/klp-mes/src/main/resources/mapper/roll/MesRollChangeMapper.xml +++ b/klp-mes/src/main/resources/mapper/roll/MesRollChangeMapper.xml @@ -15,6 +15,37 @@ LIMIT 1 + + + + + + - + SELECT + COUNT(DISTINCT mc.coil_id) AS coilCount, + IFNULL(SUM(mc.actual_length), 0) AS totalLength, + IFNULL(SUM(mc.net_weight), 0) AS totalWeight FROM wms_coil_pending_action cpa INNER JOIN wms_material_coil mc - ON FIND_IN_SET(mc.coil_id, cpa.processed_coil_ids) > 0 + ON FIND_IN_SET(mc.coil_id, cpa.processed_coil_ids) > 0 WHERE cpa.del_flag = 0 AND cpa.action_status = 2 AND cpa.action_type IN (205, 504, 524) diff --git a/klp-ui/src/api/mes/roll/rollChange.js b/klp-ui/src/api/mes/roll/rollChange.js index 0e0a5eb1..68f1d541 100644 --- a/klp-ui/src/api/mes/roll/rollChange.js +++ b/klp-ui/src/api/mes/roll/rollChange.js @@ -18,12 +18,11 @@ export function getCurrentRolls(standNo) { }) } -// 查询指定机架当前轧辊实时工作长度(m) -export function getWorkLength(standNo) { +// 查询各机架各辊位实时工作绩效(workLength/coilCount/totalWeight) +export function getRollPerformance() { return request({ - url: '/mes/rollChange/workLength', - method: 'get', - params: { standNo } + url: '/mes/rollChange/performance', + method: 'get' }) } diff --git a/klp-ui/src/views/mes/roll/working/index.vue b/klp-ui/src/views/mes/roll/working/index.vue index d004eb43..41a8d0b9 100644 --- a/klp-ui/src/views/mes/roll/working/index.vue +++ b/klp-ui/src/views/mes/roll/working/index.vue @@ -85,30 +85,51 @@ - - -
- 可用轧辊(离线) - 刷新 -
- - - - - - - - - - - -
+ +
+ + + +
+ 可用轧辊(离线) + 刷新 +
+ + + + + + + + + + +
+ + + +
+ 工作绩效(实时) + 刷新 +
+ + + + + + + + + +
+ +
@@ -145,17 +166,36 @@ {{ scope.row.changeType }} - - - - - - + + + + + + + + + + +