From b739a1cde9958f6ee7616990ebd5b28fe195977b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Wed, 28 Jan 2026 17:43:49 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor(wms/coil):=20=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E9=92=A2=E5=8D=B7=E6=9B=B4=E6=96=B0=E9=80=BB=E8=BE=91=E5=B9=B6?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=A1=A8=E5=8D=95=E9=AA=8C=E8=AF=81=E8=A7=84?= =?UTF-8?q?=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用updateMaterialCoilSimple替换updateMaterialCoil以简化更新逻辑 - 移除部分非必要的表单验证规则 - 为钢卷选择器添加状态筛选条件 --- klp-ui/src/views/wms/coil/do/packing.vue | 43 ++++++++++++------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/klp-ui/src/views/wms/coil/do/packing.vue b/klp-ui/src/views/wms/coil/do/packing.vue index 880d27db..0249a442 100644 --- a/klp-ui/src/views/wms/coil/do/packing.vue +++ b/klp-ui/src/views/wms/coil/do/packing.vue @@ -244,7 +244,7 @@ + + + + .oee-loading-main { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + } + .oee-loading-card { + max-width: 520px; + padding: 24px 28px; + background: #ffffff; + border-radius: 4px; + box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12); + text-align: left; + } + + .oee-loading-title { + font-size: 16px; + font-weight: 600; + margin-bottom: 8px; + } + + .oee-loading-text { + font-size: 13px; + color: #606266; + line-height: 1.6; + margin-bottom: 12px; + } + + .oee-report-header { + border-bottom: 1px solid #ebeef5; + padding-bottom: 12px; + margin-bottom: 16px; + } + + .oee-report-meta { + display: flex; + justify-content: flex-start; + column-gap: 24px; + font-size: 12px; + color: #606266; + margin-bottom: 6px; + } + + .oee-report-query-form { + display: flex; + justify-content: flex-end; + } + + .oee-section { + margin-top: 18px; + } + + .oee-section-title { + font-size: 15px; + font-weight: 600; + margin-bottom: 8px; + } + + .oee-charts { + display: grid; + grid-template-columns: 1fr; + gap: 12px; + } + + .oee-chart-card { + border: 1px solid #ebeef5; + border-radius: 4px; + padding: 10px 12px; + } + + .oee-chart-title { + font-size: 13px; + font-weight: 600; + margin-bottom: 6px; + } + + .oee-chart { + width: 100%; + height: 260px; + } + + .oee-paragraph { + font-size: 13px; + line-height: 1.6; + color: #606266; + margin-bottom: 8px; + } + + .oee-subsection { + margin-top: 10px; + } + + .oee-subsection-title { + font-size: 14px; + font-weight: 500; + margin-bottom: 6px; + } + + .oee-kpi-table, + .oee-daily-table, + .oee-loss-table, + .oee-events-table { + font-size: 12px; + } + + .oee-report-aside { + width: 320px; + position: sticky; + top: 72px; + align-self: flex-start; + } + + .oee-formula-card { + background: #ffffff; + padding: 16px 18px; + border-radius: 4px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); + } + + .oee-formula-title { + font-size: 14px; + font-weight: 600; + margin-bottom: 8px; + } + + .oee-formula-body { + font-size: 12px; + color: #606266; + } + + .oee-formula-caption { + margin-top: 10px; + margin-bottom: 2px; + font-weight: 500; + } + + .math-block { + margin: 4px 0; + } + + .oee-formula-footnote { + margin-top: 10px; + font-size: 11px; + color: #909399; + } + + .oee-bg-progress { + margin-top: 8px; + width: 100%; + } + + .oee-bg-progress-text { + margin-top: 4px; + font-size: 12px; + color: #909399; + } + + /* 让进度数字在条外侧显示,避免被遮挡 */ + .oee-bg-progress :deep(.el-progress__text) { + margin-left: 8px; + color: #606266; + font-weight: 500; + } + + .oee-regression-item { + padding: 8px 0; + border-top: 1px dashed #ebeef5; + } + + .oee-regression-title { + font-weight: 600; + margin-bottom: 4px; + } + + .oee-regression-row { + display: flex; + flex-wrap: wrap; + gap: 8px 12px; + } + + + \ No newline at end of file diff --git a/klp-wms/src/main/java/com/klp/controller/WmsCoilPendingActionController.java b/klp-wms/src/main/java/com/klp/controller/WmsCoilPendingActionController.java index b066c20b..887190ff 100644 --- a/klp-wms/src/main/java/com/klp/controller/WmsCoilPendingActionController.java +++ b/klp-wms/src/main/java/com/klp/controller/WmsCoilPendingActionController.java @@ -18,9 +18,13 @@ import com.klp.common.core.validate.EditGroup; import com.klp.common.enums.BusinessType; import com.klp.common.utils.poi.ExcelUtil; import com.klp.domain.vo.WmsCoilPendingActionVo; +import com.klp.domain.vo.TheoryCycleRegressionResultVo; import com.klp.domain.bo.WmsCoilPendingActionBo; import com.klp.service.IWmsCoilPendingActionService; import com.klp.common.core.page.TableDataInfo; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; /** * 钢卷待操作 @@ -133,5 +137,17 @@ public class WmsCoilPendingActionController extends BaseController { public R cancelAction(@PathVariable("actionId") Long actionId) { return toAjax(iWmsCoilPendingActionService.cancelAction(actionId)); } + + /** + * 计算理论节拍回归(默认近6个月),并返回散点+拟合线 + */ + @GetMapping("/theoryCycle/regression") + public R theoryCycleRegression( + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime, + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, + @RequestParam(value = "includePoints", required = false, defaultValue = "false") Boolean includePoints, + @RequestParam(value = "maxPoints", required = false, defaultValue = "2000") Integer maxPoints) { + return R.ok(iWmsCoilPendingActionService.calcTheoryCycleRegression(startTime, endTime, includePoints, maxPoints)); + } } diff --git a/klp-wms/src/main/java/com/klp/domain/vo/TheoryCyclePointVo.java b/klp-wms/src/main/java/com/klp/domain/vo/TheoryCyclePointVo.java new file mode 100644 index 00000000..9305d915 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/vo/TheoryCyclePointVo.java @@ -0,0 +1,33 @@ +package com.klp.domain.vo; + +import lombok.Data; + +import java.util.Date; + +/** + * 理论节拍散点 + */ +@Data +public class TheoryCyclePointVo { + + /** + * X:产量(吨) + */ + private Double weightTon; + + /** + * Y:耗时(分钟) + */ + private Double durationMin; + + /** + * 对应的动作ID + */ + private Long actionId; + + /** + * 创建时间(便于前端提示) + */ + private Date createTime; +} + diff --git a/klp-wms/src/main/java/com/klp/domain/vo/TheoryCycleRegressionResultVo.java b/klp-wms/src/main/java/com/klp/domain/vo/TheoryCycleRegressionResultVo.java new file mode 100644 index 00000000..ed07c3ef --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/vo/TheoryCycleRegressionResultVo.java @@ -0,0 +1,18 @@ +package com.klp.domain.vo; + +import lombok.Data; + +import java.util.List; + +/** + * 理论节拍回归结果集合 + */ +@Data +public class TheoryCycleRegressionResultVo { + + /** + * 产线回归结果列表 + */ + private List lines; +} + diff --git a/klp-wms/src/main/java/com/klp/domain/vo/TheoryCycleRegressionVo.java b/klp-wms/src/main/java/com/klp/domain/vo/TheoryCycleRegressionVo.java new file mode 100644 index 00000000..a6a74d65 --- /dev/null +++ b/klp-wms/src/main/java/com/klp/domain/vo/TheoryCycleRegressionVo.java @@ -0,0 +1,49 @@ +package com.klp.domain.vo; + +import lombok.Data; + +import java.util.Date; +import java.util.List; + +/** + * 单条产线的理论节拍线性回归结果 + */ +@Data +public class TheoryCycleRegressionVo { + + private String lineId; + + private String lineName; + + /** + * 斜率:分钟/吨 + */ + private Double slopeMinPerTon; + + /** + * 截距:分钟 + */ + private Double interceptMin; + + /** + * 拟合优度 + */ + private Double r2; + + private Integer sampleCount; + + private Date startTime; + + private Date endTime; + + /** + * 散点数据 + */ + private List points; + + /** + * 拟合线两个端点(前端可直接画线) + */ + private List linePoints; +} + diff --git a/klp-wms/src/main/java/com/klp/service/IWmsCoilPendingActionService.java b/klp-wms/src/main/java/com/klp/service/IWmsCoilPendingActionService.java index 528ef962..3a3f09d9 100644 --- a/klp-wms/src/main/java/com/klp/service/IWmsCoilPendingActionService.java +++ b/klp-wms/src/main/java/com/klp/service/IWmsCoilPendingActionService.java @@ -7,6 +7,8 @@ import com.klp.common.core.page.TableDataInfo; import java.util.Collection; import java.util.List; +import java.util.Date; +import com.klp.domain.vo.TheoryCycleRegressionResultVo; /** * 钢卷待操作Service接口 @@ -65,5 +67,18 @@ public interface IWmsCoilPendingActionService { * 取消操作 */ Boolean cancelAction(Long actionId); + + /** + * 计算理论节拍线性回归(默认近6个月),同时返回散点用于前端绘图并将结果缓存。 + */ + TheoryCycleRegressionResultVo calcTheoryCycleRegression(Date startTime, Date endTime); + + /** + * 计算理论节拍线性回归(可选择是否返回散点;并对散点数量进行上限控制)。 + * + * @param includePoints 是否返回散点 points(默认 false,避免结果过大) + * @param maxPoints 最大散点数(includePoints=true 时生效) + */ + TheoryCycleRegressionResultVo calcTheoryCycleRegression(Date startTime, Date endTime, Boolean includePoints, Integer maxPoints); } diff --git a/klp-wms/src/main/java/com/klp/service/impl/WmsCoilPendingActionServiceImpl.java b/klp-wms/src/main/java/com/klp/service/impl/WmsCoilPendingActionServiceImpl.java index 6f679aac..ed845630 100644 --- a/klp-wms/src/main/java/com/klp/service/impl/WmsCoilPendingActionServiceImpl.java +++ b/klp-wms/src/main/java/com/klp/service/impl/WmsCoilPendingActionServiceImpl.java @@ -2,28 +2,36 @@ package com.klp.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.klp.common.core.domain.PageQuery; -import com.klp.common.core.domain.entity.SysUser; -import com.klp.common.core.page.TableDataInfo; -import com.klp.common.utils.StringUtils; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.klp.common.core.domain.PageQuery; +import com.klp.common.core.page.TableDataInfo; import com.klp.common.helper.LoginHelper; +import com.klp.common.utils.StringUtils; +import com.klp.domain.WmsCoilPendingAction; import com.klp.domain.WmsMaterialCoil; -import com.klp.domain.vo.WmsMaterialCoilVo; +import com.klp.domain.bo.WmsCoilPendingActionBo; +import com.klp.domain.vo.TheoryCyclePointVo; +import com.klp.domain.vo.TheoryCycleRegressionResultVo; +import com.klp.domain.vo.TheoryCycleRegressionVo; +import com.klp.domain.vo.WmsCoilPendingActionVo; +import com.klp.mapper.WmsCoilPendingActionMapper; import com.klp.mapper.WmsMaterialCoilMapper; -import com.klp.service.IWmsMaterialCoilService; +import com.klp.service.IWmsCoilPendingActionService; import com.klp.system.service.ISysUserService; import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; -import com.klp.domain.bo.WmsCoilPendingActionBo; -import com.klp.domain.vo.WmsCoilPendingActionVo; -import com.klp.domain.WmsCoilPendingAction; -import com.klp.mapper.WmsCoilPendingActionMapper; -import com.klp.service.IWmsCoilPendingActionService; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -40,6 +48,9 @@ public class WmsCoilPendingActionServiceImpl implements IWmsCoilPendingActionSer private final ISysUserService userService; private final WmsMaterialCoilMapper materialCoilMapper; + private final StringRedisTemplate stringRedisTemplate; + + private static final String REDIS_KEY_IDEAL_CYCLE = "oee:ideal-cycle-time"; /** * 查询钢卷待操作 @@ -248,5 +259,262 @@ public class WmsCoilPendingActionServiceImpl implements IWmsCoilPendingActionSer action.setActionStatus(3); // 已取消 return baseMapper.updateById(action) > 0; } + + @Override + public TheoryCycleRegressionResultVo calcTheoryCycleRegression(Date startTime, Date endTime) { + return calcTheoryCycleRegression(startTime, endTime, true, 2000); + } + + @Override + public TheoryCycleRegressionResultVo calcTheoryCycleRegression(Date startTime, Date endTime, Boolean includePoints, Integer maxPoints) { + LocalDateTime end = endTime == null ? LocalDateTime.now() : toLocalDateTime(endTime); + LocalDateTime start = startTime == null ? end.minusMonths(6) : toLocalDateTime(startTime); + + boolean inc = includePoints != null && includePoints; + int limit = (maxPoints == null || maxPoints <= 0) ? 2000 : maxPoints; + TheoryCycleRegressionVo sy = buildRegression("SY", "酸轧线", 11, start, end, false, inc, limit); + TheoryCycleRegressionVo dx1 = buildRegression("DX1", "镀锌一线", 501, start, end, true, inc, limit); + + cacheIdealCycle(sy); + cacheIdealCycle(dx1); + + TheoryCycleRegressionResultVo result = new TheoryCycleRegressionResultVo(); + result.setLines(Arrays.asList(sy, dx1)); + return result; + } + + private TheoryCycleRegressionVo buildRegression(String lineId, String lineName, int actionType, + LocalDateTime start, LocalDateTime end, + boolean parseRemarkIds, + boolean includePoints, int maxPoints) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(WmsCoilPendingAction::getActionType, actionType) + .eq(WmsCoilPendingAction::getDelFlag, 0) + .eq(WmsCoilPendingAction::getActionStatus, 2) + .ge(WmsCoilPendingAction::getCreateTime, Date.from(start.atZone(ZoneId.systemDefault()).toInstant())) + .le(WmsCoilPendingAction::getCreateTime, Date.from(end.atZone(ZoneId.systemDefault()).toInstant())); + + List actions = baseMapper.selectList(lqw); + if (actions == null || actions.isEmpty()) { + TheoryCycleRegressionVo vo = new TheoryCycleRegressionVo(); + vo.setLineId(lineId); + vo.setLineName(lineName); + vo.setStartTime(Date.from(start.atZone(ZoneId.systemDefault()).toInstant())); + vo.setEndTime(Date.from(end.atZone(ZoneId.systemDefault()).toInstant())); + vo.setSampleCount(0); + vo.setPoints(Collections.emptyList()); + vo.setLinePoints(Collections.emptyList()); + return vo; + } + + // 预先收集所有需要的钢卷 ID,一次性批量查询,避免在循环中逐条访问数据库 + Set allCoilIds = new HashSet<>(); + for (WmsCoilPendingAction action : actions) { + if (action.getCreateTime() == null || action.getCompleteTime() == null) { + continue; + } + if (parseRemarkIds) { + List ids = parseIdsFromRemark(action.getRemark()); + allCoilIds.addAll(ids); + } else { + if (action.getCoilId() != null) { + allCoilIds.add(action.getCoilId()); + } + } + } + + Map weightTonMap = new HashMap<>(); + if (!allCoilIds.isEmpty()) { + List coils = materialCoilMapper.selectBatchIds(allCoilIds); + if (coils != null) { + for (WmsMaterialCoil coil : coils) { + if (coil == null || coil.getCoilId() == null) continue; + BigDecimal net = coil.getNetWeight(); + BigDecimal gross = coil.getGrossWeight(); + BigDecimal weightKg = net != null && net.compareTo(BigDecimal.ZERO) > 0 ? net : gross; + if (weightKg == null || weightKg.compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + double ton = weightKg.divide(BigDecimal.valueOf(1000), 6, RoundingMode.HALF_UP).doubleValue(); + weightTonMap.put(coil.getCoilId(), ton); + } + } + } + + List points = new ArrayList<>(); + for (WmsCoilPendingAction action : actions) { + if (action.getCreateTime() == null || action.getCompleteTime() == null) { + continue; + } + long minutes = Duration.between( + toLocalDateTime(action.getCreateTime()), + toLocalDateTime(action.getCompleteTime()) + ).toMinutes(); + if (minutes <= 0) { + continue; + } + double weightTon = 0D; + if (parseRemarkIds) { + List ids = parseIdsFromRemark(action.getRemark()); + for (Long id : ids) { + Double wt = weightTonMap.get(id); + if (wt != null && wt > 0D) { + weightTon += wt; + } + } + } else { + if (action.getCoilId() != null) { + Double wt = weightTonMap.get(action.getCoilId()); + if (wt != null && wt > 0D) { + weightTon = wt; + } + } + } + if (weightTon <= 0D) { + continue; + } + TheoryCyclePointVo p = new TheoryCyclePointVo(); + p.setActionId(action.getActionId()); + p.setCreateTime(action.getCreateTime()); + p.setDurationMin((double) minutes); + p.setWeightTon(weightTon); + points.add(p); + } + + TheoryCycleRegressionVo vo = new TheoryCycleRegressionVo(); + vo.setLineId(lineId); + vo.setLineName(lineName); + vo.setStartTime(Date.from(start.atZone(ZoneId.systemDefault()).toInstant())); + vo.setEndTime(Date.from(end.atZone(ZoneId.systemDefault()).toInstant())); + vo.setSampleCount(points.size()); + if (includePoints) { + vo.setPoints(samplePoints(points, maxPoints)); + } else { + vo.setPoints(Collections.emptyList()); + } + + RegressionStat stat = linearRegression(points); + vo.setSlopeMinPerTon(stat.slope); + vo.setInterceptMin(stat.intercept); + vo.setR2(stat.r2); + vo.setLinePoints(stat.linePoints); + return vo; + } + + /** + * 散点抽样:避免返回体过大导致网络/序列化问题。 + */ + private List samplePoints(List points, int maxPoints) { + if (points == null || points.isEmpty()) { + return Collections.emptyList(); + } + if (maxPoints <= 0 || points.size() <= maxPoints) { + return points; + } + int n = points.size(); + double step = (double) n / (double) maxPoints; + List sampled = new ArrayList<>(maxPoints); + for (int i = 0; i < maxPoints; i++) { + int idx = (int) Math.floor(i * step); + if (idx < 0) idx = 0; + if (idx >= n) idx = n - 1; + sampled.add(points.get(idx)); + } + return sampled; + } + + private void cacheIdealCycle(TheoryCycleRegressionVo vo) { + if (vo == null || vo.getSlopeMinPerTon() == null) { + return; + } + String field = vo.getLineId() == null ? "UNKNOWN" : vo.getLineId().toUpperCase(); + stringRedisTemplate.opsForHash().put(REDIS_KEY_IDEAL_CYCLE, field, vo.getSlopeMinPerTon().toString()); + if (vo.getInterceptMin() != null) { + stringRedisTemplate.opsForHash().put(REDIS_KEY_IDEAL_CYCLE + ":intercept", field, vo.getInterceptMin().toString()); + } + } + + private RegressionStat linearRegression(List points) { + RegressionStat stat = new RegressionStat(); + if (points == null || points.size() < 2) { + return stat; + } + double sumX = 0, sumY = 0, sumXX = 0, sumXY = 0; + for (TheoryCyclePointVo p : points) { + double x = p.getWeightTon(); + double y = p.getDurationMin(); + sumX += x; + sumY += y; + sumXX += x * x; + sumXY += x * y; + } + int n = points.size(); + double denominator = n * sumXX - sumX * sumX; + if (denominator == 0) { + return stat; + } + double slope = (n * sumXY - sumX * sumY) / denominator; + double intercept = (sumY - slope * sumX) / n; + + double ssTot = 0, ssRes = 0; + double meanY = sumY / n; + for (TheoryCyclePointVo p : points) { + double y = p.getDurationMin(); + double yHat = slope * p.getWeightTon() + intercept; + ssTot += Math.pow(y - meanY, 2); + ssRes += Math.pow(y - yHat, 2); + } + double r2 = ssTot == 0 ? 0 : 1 - ssRes / ssTot; + + stat.slope = slope; + stat.intercept = intercept; + stat.r2 = r2; + stat.linePoints = buildLinePoints(points, slope, intercept); + return stat; + } + + private List buildLinePoints(List points, double slope, double intercept) { + if (points == null || points.isEmpty()) { + return Collections.emptyList(); + } + double minX = points.stream().mapToDouble(TheoryCyclePointVo::getWeightTon).min().orElse(0D); + double maxX = points.stream().mapToDouble(TheoryCyclePointVo::getWeightTon).max().orElse(0D); + List line = new ArrayList<>(); + TheoryCyclePointVo p1 = new TheoryCyclePointVo(); + p1.setWeightTon(minX); + p1.setDurationMin(slope * minX + intercept); + TheoryCyclePointVo p2 = new TheoryCyclePointVo(); + p2.setWeightTon(maxX); + p2.setDurationMin(slope * maxX + intercept); + line.add(p1); + line.add(p2); + return line; + } + + private List parseIdsFromRemark(String remark) { + if (StringUtils.isBlank(remark)) { + return Collections.emptyList(); + } + Matcher matcher = Pattern.compile("\\d+").matcher(remark); + List ids = new ArrayList<>(); + while (matcher.find()) { + try { + ids.add(Long.parseLong(matcher.group())); + } catch (NumberFormatException ignore) { + } + } + return ids; + } + + private LocalDateTime toLocalDateTime(Date date) { + return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + } + + private static class RegressionStat { + Double slope; + Double intercept; + Double r2; + List linePoints = Collections.emptyList(); + } } 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 96725f70..dfb7781b 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 @@ -394,15 +394,6 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { qw.eq(StringUtils.isNotBlank(bo.getTemperGrade()), "mc.temper_grade", bo.getTemperGrade()); // 独占状态 qw.eq(bo.getExclusiveStatus() != null, "mc.exclusive_status", bo.getExclusiveStatus()); - //逻辑删除 - qw.eq("mc.del_flag", 0); - // 按创建时间范围筛选 - if (bo.getByCreateTimeStart() != null) { - qw.ge("mc.create_time", bo.getByCreateTimeStart()); - } - if (bo.getByCreateTimeEnd() != null) { - qw.le("mc.create_time", bo.getByCreateTimeEnd()); - } // 统一处理 warehouseId 与 warehouseIds: List warehouseIdList = new ArrayList<>(); if (bo.getWarehouseId() != null) { @@ -571,13 +562,17 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { // "WHERE dp.del_flag = 0 AND dp.coil IS NOT NULL AND dp.coil <> '' " + // "AND FIND_IN_SET(CAST(mc.coil_id AS CHAR), dp.coil))"); // } - + //逻辑删除 + qw.eq("mc.del_flag", 0); //把team字段作为筛选条件 qw.eq(StringUtils.isNotBlank(bo.getTeam()), "mc.team", bo.getTeam()); //根据开始时间和结束时间筛选修改时间 qw.ge(bo.getStartTime() != null, "mc.update_time", bo.getStartTime()); qw.le(bo.getEndTime() != null, "mc.update_time", bo.getEndTime()); + qw.ge(bo.getByCreateTimeStart() != null, "mc.create_time", bo.getByCreateTimeStart()); + qw.le(bo.getByCreateTimeEnd() != null, "mc.create_time", bo.getByCreateTimeEnd()); + // 处理发货时间筛选逻辑(核心修改部分) if (bo.getByExportTimeStart() != null || bo.getByExportTimeEnd() != null) { // 开启OR条件分组:满足情况1 或 情况2 @@ -618,50 +613,69 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService { @Override public Map getDuplicateCoilGroups() { - // 使用优化的数据库查询方法,直接获取重复入场卷号的钢卷信息 - List enterDuplicates = baseMapper.selectDuplicateEnterCoilNoList(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(WmsMaterialCoil::getDataType, 1); + lqw.eq(WmsMaterialCoil::getDelFlag, 0); + List all = baseMapper.selectList(lqw); - // 使用优化的数据库查询方法,直接获取重复当前卷号的钢卷信息 - List currentDuplicates = baseMapper.selectDuplicateCurrentCoilNoList(); - - // 按入场卷号分组重复项 - Map> enterGrouped = enterDuplicates.stream() + Map> enterGrouped = all.stream() .filter(e -> StringUtils.isNotBlank(e.getEnterCoilNo())) - .collect(Collectors.groupingBy(WmsMaterialCoilVo::getEnterCoilNo)); - - // 按当前卷号分组重复项 - Map> currentGrouped = currentDuplicates.stream() + .collect(Collectors.groupingBy(WmsMaterialCoil::getEnterCoilNo)); + Map> currentGrouped = all.stream() .filter(e -> StringUtils.isNotBlank(e.getCurrentCoilNo())) - .collect(Collectors.groupingBy(WmsMaterialCoilVo::getCurrentCoilNo)); + .collect(Collectors.groupingBy(WmsMaterialCoil::getCurrentCoilNo)); - // 构建入场卷号重复组 List> enterGroups = enterGrouped.entrySet().stream() - .filter(entry -> entry.getValue() != null && entry.getValue().size() > 1) - .map(entry -> { - Map group = new HashMap<>(); - group.put("enterCoilNo", entry.getKey()); - group.put("coils", entry.getValue()); - return group; + .filter(en -> en.getValue() != null && en.getValue().size() > 1) + .map(en -> { + List vos = en.getValue().stream().map(this::toVoBasic).collect(Collectors.toList()); + Map m = new HashMap<>(); + m.put("enterCoilNo", en.getKey()); + m.put("coils", vos); + return m; }) .collect(Collectors.toList()); - // 构建当前卷号重复组 List> currentGroups = currentGrouped.entrySet().stream() - .filter(entry -> entry.getValue() != null && entry.getValue().size() > 1) - .map(entry -> { - Map group = new HashMap<>(); - group.put("currentCoilNo", entry.getKey()); - group.put("coils", entry.getValue()); - return group; + .filter(en -> en.getValue() != null && en.getValue().size() > 1) + .map(en -> { + List vos = en.getValue().stream().map(this::toVoBasic).collect(Collectors.toList()); + Map m = new HashMap<>(); + m.put("currentCoilNo", en.getKey()); + m.put("coils", vos); + return m; }) .collect(Collectors.toList()); + // 可选:批量填充关联对象信息 + List allVos = new ArrayList<>(); + for (Map g : enterGroups) { + Object list = g.get("coils"); + if (list instanceof List) { + allVos.addAll((List) list); + } + } + for (Map g : currentGroups) { + Object list = g.get("coils"); + if (list instanceof List) { + allVos.addAll((List) list); + } + } + if (!allVos.isEmpty()) { + fillRelatedObjectsBatch(allVos); + } + Map result = new HashMap<>(); result.put("enterGroups", enterGroups); result.put("currentGroups", currentGroups); return result; } + private WmsMaterialCoilVo toVoBasic(WmsMaterialCoil e) { + WmsMaterialCoilVo vo = new WmsMaterialCoilVo(); + BeanUtils.copyProperties(e, vo); + return vo; + } /** * 构建 OR 连接的 LIKE 子句,使用 MyBatis-Plus apply 的 {index} 占位符并将参数加入 args。