diff --git a/klp-pocket/src/main/java/com/klp/pocket/acid/domain/vo/AcidOeeDailySummaryVo.java b/klp-pocket/src/main/java/com/klp/pocket/acid/domain/vo/AcidOeeDailySummaryVo.java index abac929f..cb1977d2 100644 --- a/klp-pocket/src/main/java/com/klp/pocket/acid/domain/vo/AcidOeeDailySummaryVo.java +++ b/klp-pocket/src/main/java/com/klp/pocket/acid/domain/vo/AcidOeeDailySummaryVo.java @@ -3,7 +3,6 @@ package com.klp.pocket.acid.domain.vo; import lombok.Data; import java.math.BigDecimal; -import java.util.Date; /** * 酸轧线OEE日汇总视图对象 @@ -45,18 +44,36 @@ public class AcidOeeDailySummaryVo { /** 总产量(卷) */ private Long totalOutputCoil; - /** 良品量(吨) */ + /** 良品量(A系列,吨) */ private BigDecimal goodOutputTon; - /** 良品量(卷) */ + /** 良品量(A系列,卷) */ private Long goodOutputCoil; - /** 不良量(吨)= total_output_ton - good_output_ton */ + /** 合格品量(B系列,吨) */ + private BigDecimal qualifiedOutputTon; + + /** 合格品量(B系列,卷) */ + private Long qualifiedOutputCoil; + + /** 合格品合计(A+B,吨) */ + private BigDecimal abOutputTon; + + /** 合格品合计(A+B,卷) */ + private Long abOutputCoil; + + /** 次品量(C/D系列,吨) */ private BigDecimal defectOutputTon; - /** 不良量(卷)= total_output_coil - good_output_coil */ + /** 次品量(C/D系列,卷) */ private Long defectOutputCoil; + /** 待判级量(O系列,吨) */ + private BigDecimal pendingOutputTon; + + /** 待判级量(O系列,卷) */ + private Long pendingOutputCoil; + /** 理论节拍(min/吨;回归斜率) */ private BigDecimal idealCycleTimeMinPerTon; @@ -72,9 +89,18 @@ public class AcidOeeDailySummaryVo { /** 派生指标:性能稼动率(卷维度) */ private BigDecimal performanceCoil; - /** 派生指标:良品率 */ + /** 派生指标:良品率(A/总量) */ private BigDecimal quality; + /** 派生指标:合格品率(A+B/总量) */ + private BigDecimal qualifiedRate; + + /** 派生指标:次品率(C/D系列/总量) */ + private BigDecimal defectRate; + + /** 派生指标:待判级率(O系列/总量) */ + private BigDecimal pendingRate; + /** 派生指标:OEE(建议以吨维度为主) */ private BigDecimal oee; } diff --git a/klp-pocket/src/main/java/com/klp/pocket/acid/service/impl/AcidOeeServiceImpl.java b/klp-pocket/src/main/java/com/klp/pocket/acid/service/impl/AcidOeeServiceImpl.java index 2081a4e9..81954864 100644 --- a/klp-pocket/src/main/java/com/klp/pocket/acid/service/impl/AcidOeeServiceImpl.java +++ b/klp-pocket/src/main/java/com/klp/pocket/acid/service/impl/AcidOeeServiceImpl.java @@ -41,8 +41,8 @@ import java.util.Set; @Service public class AcidOeeServiceImpl implements IAcidOeeService { - /** 次品判级集合:命中这些 quality_status 判为次品 */ - private static final Set SCRAP_QUALITY_STATUS = new HashSet<>( + /** 次品判级集合(C/D系列) */ + private static final Set CD_SERIES = new HashSet<>( Arrays.asList("C+", "C", "C-", "D+", "D", "D-") ); @@ -105,11 +105,17 @@ public class AcidOeeServiceImpl implements IAcidOeeService { List coilInfos = coilInfoByDate.get(statDate); calculateQualityOutput(summary, coilInfos); } else { - // 如果没有卷号,默认全部为良品(或根据业务规则处理) - summary.setGoodOutputTon(summary.getTotalOutputTon()); - summary.setGoodOutputCoil(summary.getTotalOutputCoil()); + // 没有卷明细时,全部归待判级 + summary.setGoodOutputTon(BigDecimal.ZERO); + summary.setGoodOutputCoil(0L); + summary.setQualifiedOutputTon(BigDecimal.ZERO); + summary.setQualifiedOutputCoil(0L); + summary.setAbOutputTon(BigDecimal.ZERO); + summary.setAbOutputCoil(0L); summary.setDefectOutputTon(BigDecimal.ZERO); summary.setDefectOutputCoil(0L); + summary.setPendingOutputTon(summary.getTotalOutputTon()); + summary.setPendingOutputCoil(summary.getTotalOutputCoil()); } calculateDerivedMetrics(summary); @@ -378,51 +384,64 @@ public class AcidOeeServiceImpl implements IAcidOeeService { * 卷号信息内部类 */ private static class CoilInfo { - final String coilNo; final BigDecimal weight; final String qualityStatus; CoilInfo(String coilNo, BigDecimal weight, String qualityStatus) { - this.coilNo = coilNo; this.weight = weight; this.qualityStatus = qualityStatus; } } /** - * 计算良品/次品产量 + * 计算质量细分产量:A良品、B合格品、C/D次品、O待判级。 */ private void calculateQualityOutput(AcidOeeDailySummaryVo summary, List coilInfos) { - BigDecimal goodTon = BigDecimal.ZERO; - long goodCoil = 0L; - BigDecimal defectTon = BigDecimal.ZERO; - long defectCoil = 0L; + BigDecimal aTon = BigDecimal.ZERO; + long aCoil = 0L; + BigDecimal bTon = BigDecimal.ZERO; + long bCoil = 0L; + BigDecimal cdTon = BigDecimal.ZERO; + long cdCoil = 0L; + BigDecimal oTon = BigDecimal.ZERO; + long oCoil = 0L; + for (CoilInfo coilInfo : coilInfos) { BigDecimal coilWeight = coilInfo.weight != null ? coilInfo.weight : BigDecimal.ZERO; - String qualityStatus = StringUtils.trim(coilInfo.qualityStatus); + String qualityStatus = StringUtils.upperCase(StringUtils.trim(coilInfo.qualityStatus)); - // 没有判级时按良品处理(避免再次跨库匹配导致错配) - if (StringUtils.isBlank(qualityStatus)) { - goodTon = goodTon.add(coilWeight); - goodCoil++; + if (StringUtils.isBlank(qualityStatus) || "O".equals(qualityStatus)) { + oTon = oTon.add(coilWeight); + oCoil++; continue; } - if (SCRAP_QUALITY_STATUS.contains(qualityStatus)) { - // 次品 - defectTon = defectTon.add(coilWeight); - defectCoil++; + if (qualityStatus.startsWith("A")) { + aTon = aTon.add(coilWeight); + aCoil++; + } else if (qualityStatus.startsWith("B")) { + bTon = bTon.add(coilWeight); + bCoil++; + } else if (CD_SERIES.contains(qualityStatus)) { + cdTon = cdTon.add(coilWeight); + cdCoil++; } else { - // 良品 - goodTon = goodTon.add(coilWeight); - goodCoil++; + // 未识别等级统一归待判级 + oTon = oTon.add(coilWeight); + oCoil++; } } - summary.setGoodOutputTon(goodTon); - summary.setGoodOutputCoil(goodCoil); - summary.setDefectOutputTon(defectTon); - summary.setDefectOutputCoil(defectCoil); + summary.setGoodOutputTon(aTon); + summary.setGoodOutputCoil(aCoil); + summary.setQualifiedOutputTon(bTon); + summary.setQualifiedOutputCoil(bCoil); + summary.setAbOutputTon(aTon.add(bTon)); + summary.setAbOutputCoil(aCoil + bCoil); + summary.setDefectOutputTon(cdTon); + summary.setDefectOutputCoil(cdCoil); + summary.setPendingOutputTon(oTon); + summary.setPendingOutputCoil(oCoil); } /** @@ -471,12 +490,29 @@ public class AcidOeeServiceImpl implements IAcidOeeService { summary.setPerformanceCoil(performanceCoil); } - // 良品率 + // 质量细分比率 if (totalOutputTon != null && totalOutputTon.compareTo(BigDecimal.ZERO) > 0) { - BigDecimal goodOutputTon = summary.getGoodOutputTon() != null ? summary.getGoodOutputTon() : BigDecimal.ZERO; - BigDecimal quality = goodOutputTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP) + BigDecimal aTon = summary.getGoodOutputTon() != null ? summary.getGoodOutputTon() : BigDecimal.ZERO; + BigDecimal bTon = summary.getQualifiedOutputTon() != null ? summary.getQualifiedOutputTon() : BigDecimal.ZERO; + BigDecimal cdTon = summary.getDefectOutputTon() != null ? summary.getDefectOutputTon() : BigDecimal.ZERO; + BigDecimal oTon = summary.getPendingOutputTon() != null ? summary.getPendingOutputTon() : BigDecimal.ZERO; + + BigDecimal quality = aTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); summary.setQuality(quality); + + BigDecimal qualifiedRate = aTon.add(bTon) + .divide(totalOutputTon, 4, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(100)); + summary.setQualifiedRate(qualifiedRate); + + BigDecimal defectRate = cdTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(100)); + summary.setDefectRate(defectRate); + + BigDecimal pendingRate = oTon.divide(totalOutputTon, 4, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(100)); + summary.setPendingRate(pendingRate); } // OEE(以吨维度为主) diff --git a/klp-ui/src/views/da/oee/index.vue b/klp-ui/src/views/da/oee/index.vue index e6b4b579..03ec38c6 100644 --- a/klp-ui/src/views/da/oee/index.vue +++ b/klp-ui/src/views/da/oee/index.vue @@ -79,11 +79,26 @@ {{ formatPercent(scope.row.performanceTon) }} - + + + + + + + + + + @@ -93,16 +108,26 @@ - + - + + + + + + + @@ -133,11 +158,26 @@ {{ formatPercent(scope.row.performanceTon) }} - + + + + + + + + + + @@ -147,16 +187,26 @@ - + - + + + + + + + @@ -263,7 +313,7 @@
  • A(时间稼动率) = (负荷时间 − 停机时间) / 负荷时间
  • P(性能稼动率,吨维度) = (理论节拍 × 产量吨) / 实际运转时间
  • -
  • Q(良品率) = 良品吨 / 总产量吨
  • +
  • Q(良品率) = A系列吨 / 总产量吨
@@ -273,8 +323,9 @@
  • 负荷时间:计划生产时间扣除计划停机后的时间
  • 停机时间:所有停机/中断(按 stop_type 汇总)的总时长
  • 实际运转时间:负荷时间 − 停机时间
  • -
  • 理论节拍:按“优良日统计口径”得到的稳定节拍(分钟/吨),由理论节拍接口提供
  • -
  • 良品/次品:按 WMS `quality_status` 判断,C+/C/C-/D+/D/D- 为次品
  • +
  • 理论节拍:先按天计算(运转时间/总吨),再取中位数并按业务口径乘以80%
  • +
  • A系列:良品;B系列:合格品;C/D系列:次品;O系列:待判级
  • +
  • 合格品率(AB) = (A+B) / 总量;次品率(CD) = CD / 总量;待判级率(O) = O / 总量
  • @@ -337,7 +388,7 @@ export default { this.formatDate(today) ], pickerOptions: { - disabledDate(time) { + disabledDate() { // 不限制选择范围,保留扩展空间 return false } @@ -365,13 +416,18 @@ export default { availability: 0, performanceTon: 0, quality: 0, + qualifiedRate: 0, + defectRate: 0, + pendingRate: 0, loadingTimeMin: 0, downtimeMin: 0, runTimeMin: 0, totalOutputTon: 0, totalOutputCoil: 0, goodOutputTon: 0, - defectOutputTon: 0 + abOutputTon: 0, + defectOutputTon: 0, + pendingOutputTon: 0 } } let sumLoading = 0 @@ -379,12 +435,17 @@ export default { let sumRun = 0 let sumTotalTon = 0 let sumGoodTon = 0 + let sumAbTon = 0 let sumDefectTon = 0 + let sumPendingTon = 0 let sumCoil = 0 let sumOee = 0 let sumA = 0 let sumP = 0 let sumQ = 0 + let sumQualifiedRate = 0 + let sumDefectRate = 0 + let sumPendingRate = 0 list.forEach(row => { sumLoading += row.loadingTimeMin || 0 @@ -392,28 +453,37 @@ export default { sumRun += row.runTimeMin || 0 sumTotalTon += Number(row.totalOutputTon || 0) sumGoodTon += Number(row.goodOutputTon || 0) + sumAbTon += Number(row.abOutputTon || 0) sumDefectTon += Number(row.defectOutputTon || 0) + sumPendingTon += Number(row.pendingOutputTon || 0) sumCoil += row.totalOutputCoil || 0 sumOee += Number(row.oee || 0) sumA += Number(row.availability || 0) sumP += Number(row.performanceTon || 0) sumQ += Number(row.quality || 0) + sumQualifiedRate += Number(row.qualifiedRate || 0) + sumDefectRate += Number(row.defectRate || 0) + sumPendingRate += Number(row.pendingRate || 0) }) const n = list.length - const defectAgg = Math.max(0, sumTotalTon - sumGoodTon) return { oee: n ? sumOee / n : 0, availability: n ? sumA / n : 0, performanceTon: n ? sumP / n : 0, quality: n ? sumQ / n : 0, + qualifiedRate: n ? sumQualifiedRate / n : 0, + defectRate: n ? sumDefectRate / n : 0, + pendingRate: n ? sumPendingRate / n : 0, loadingTimeMin: sumLoading, downtimeMin: sumDowntime, runTimeMin: sumRun, totalOutputTon: sumTotalTon, totalOutputCoil: sumCoil, goodOutputTon: sumGoodTon, - defectOutputTon: defectAgg || sumDefectTon + abOutputTon: sumAbTon, + defectOutputTon: sumDefectTon, + pendingOutputTon: sumPendingTon } } },