From c425a8afba0a76eb62d5650cc9c98c42d8339f06 Mon Sep 17 00:00:00 2001
From: zhuguifei <312353457@qq.com>
Date: 星期四, 12 三月 2026 13:01:23 +0800
Subject: [PATCH] perf: 1.优化储丝柜单柜卷包产量计算方式,支持未出料结束计算统计   2.新增储丝柜单柜卷包产量桑基图

---
 RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java |  351 ++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 240 insertions(+), 111 deletions(-)

diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java
index 2afb2fd..03254ad 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/analy/service/impl/StoreSilkInfoServiceImpl.java
@@ -102,6 +102,32 @@
             Date distimebegin = storeSilkInfoVo.getDistimebegin();
             //鍑烘枡缁撴潫鏃堕棿
             Date distimeend = storeSilkInfoVo.getDistimeend();
+            if (distimebegin == null) {
+                continue;
+            }
+            /**
+             * 缁熻鈥滃嚭鏂欒繘琛屼腑鈥濈殑鍏抽敭鐐癸細
+             * - 鍑烘枡缁撴潫鏃堕棿 distimeend 鍙兘涓虹┖锛堜粛鍦ㄥ嚭鏂欎腑锛�
+             * - 涔熷彲鑳藉凡缁忔湁缁撴潫鏃堕棿锛堝嚭鏂欏凡缁撴潫锛�
+             *
+             * 鍥犳杩欓噷缁熶竴璁$畻涓�涓�滄湰娆$粺璁$殑鏈夋晥缁撴潫鏃堕棿鈥� effectiveDistEnd锛�
+             * 1) distimeend == null 锛氳鏄庤繕鍦ㄥ嚭鏂欎腑锛屾湰娆$粺璁℃埅姝㈠埌褰撳墠鏃堕棿 now
+             * 2) distimeend != null 锛氳鏄庡凡鍑烘枡缁撴潫锛屾埅姝㈠埌 distimeend
+             * 3) 鑻� distimeend 鍦ㄦ湭鏉ワ紙鑴忔暟鎹�/鏃堕挓璇樊锛夛紝涔熸寜 now 鎴锛岄伩鍏嶇粺璁″埌鏈潵
+             *
+             * 鍚庣画鎵�鏈夋煡璇€�佺彮娆″垏鍒嗐�佹墸鍑忛兘鍩轰簬 effectiveDistEnd锛�
+             * 杩欐牱鍚屼竴濂楅�昏緫鍚屾椂閫傞厤鈥滃嚭鏂欏凡缁撴潫鈥濆拰鈥滃嚭鏂欐湭缁撴潫鈥濅袱绉嶅満鏅��
+             */
+            Date now = new Date();
+            Date effectiveDistEnd;
+            if (distimeend == null) {
+                effectiveDistEnd = now;
+            } else {
+                effectiveDistEnd = distimeend.after(now) ? now : distimeend;
+            }
+            if (!effectiveDistEnd.after(distimebegin)) {
+                continue;
+            }
 
             //鍌ㄤ笣鏌滄煖鍙�
             String siloid = storeSilkInfoVo.getSiloid();
@@ -110,11 +136,18 @@
             String containerNum = siloid.substring(lastIndex + 1);
             if (StringUtils.isEmpty(containerNum)) continue;
 
-            //鏍规嵁鍑烘枡寮�濮嬫椂闂存煡璇㈠杺涓濇満->鍌ㄤ笣鏌�->鏈哄彴瀵瑰簲鍏崇郴(feedmatch_time_data)
-            Timestamp targetTime = new Timestamp(distimebegin.getTime() + 10 * 60 * 1000); // 鏌ヨ鍑烘枡10鍒嗛挓鍚庣殑绗竴鏉¤褰曪紝淇濊瘉鏁版嵁鍑嗙‘鎬�
+            /**
+             * 鏍规嵁鍑烘枡寮�濮嬫椂闂存煡璇⑩�滃杺涓濇満 -> 鍌ㄤ笣鏌� -> 鏈哄彴(绠¢亾)鈥濆搴斿叧绯�(feedmatch_time_data)
+             *
+             * 璇存槑锛�
+             * - 杩欓噷涓嶆槸鐩存帴鐢� distimebegin锛岃�屾槸鍙栧嚭鏂欏紑濮嬪悗 10 鍒嗛挓鐨勭涓�鏉¤褰曪紝
+             *   鐩殑鏄伩寮�鍑烘枡鍒氬紑濮嬫椂鐨勬尝鍔�/鏄犲皠鏈ǔ瀹氶棶棰橈紝淇濊瘉鏄犲皠鍑嗙‘鎬с��
+             * - 鏌ヨ涓婄晫浣跨敤 effectiveDistEnd锛氬鏋滃嚭鏂欒繕娌$粨鏉燂紝灏变互褰撳墠鏃堕棿浣滀负涓婄晫锛屼粛鐒惰兘鍙栧埌瀵瑰簲鍏崇郴銆�
+             */
+            Timestamp targetTime = new Timestamp(distimebegin.getTime() + 10 * 60 * 1000); // 鍑烘枡寮�濮嬪悗10鍒嗛挓
             LambdaQueryWrapper<FeedmatchTimeData> lqw = new LambdaQueryWrapper<>();
             lqw.ge(FeedmatchTimeData::getTime, targetTime)
-                    .le(FeedmatchTimeData::getTime, distimeend) // 涓嶈兘澶т簬鍑烘枡缁撴潫鏃堕棿
+                    .le(FeedmatchTimeData::getTime, effectiveDistEnd) // 涓嶈兘澶т簬鍑烘枡缁撴潫鏃堕棿锛堝嚭鏂欎腑鍒欎娇鐢ㄥ綋鍓嶆椂闂达級
                     .orderByAsc(FeedmatchTimeData::getTime)
                     .last("LIMIT 1");
             FeedmatchTimeData feedMatch = feedmatchTimeDataMapper.selectOne(lqw);
@@ -123,11 +156,12 @@
                 continue;
             }
 
-            // feedMatch 杞琺ap  TODO 閫嗚浆map闇�楠岃瘉key鏄惁浼氶噸澶�
-            //fsRevMap鏄�嗚浆map     key->鍠備笣鏈哄搴旂殑鍌ㄤ笣鏌滃彿   value-> fs + 搴忓彿
+            // feedMatch 杞琺ap锛氶�氳繃鍙嶅悜鏄犲皠蹇�熷畾浣嶁�滆鏌滃搴斿摢涓杺涓濇満鈥濄�佲�滆鏈虹粍瀵瑰簲鍝釜绠¢亾鈥�
+            // fsRevMap锛歬ey=鍌ㄤ笣鏌滃彿鏈綅锛堝 1/2/3锛夛紝value=瀛楁鍚嶏紙濡� fs11/fs12...锛�
             Map<String, String> fsRevMap = new HashMap<>();
-            //pipeRevMap鏄�嗚浆map   key->鏈虹粍瀵瑰簲鐨勫杺涓濇満鍜岀閬�  value-> pipe + 搴忓彿
+            // pipeRevMap锛歬ey=鍠備笣鏈哄彿+绠¢亾缁勫悎锛堝 1x / 2x...锛夛紝value=瀛楁鍚嶏紙濡� pipe01/pipe02...锛�
             Map<String, String> pipeRevMap = new HashMap<>();
+            // pipeMap锛歬ey=瀛楁鍚嶏紙pipe01/pipe02...锛夛紝value=瀛楁鍊硷紙鐢ㄤ簬鍚庣画瑙f瀽鍏蜂綋绠¢亾鍙凤級
             Map<String, String> pipeMap = new HashMap<>();
             Field[] fields = feedMatch.getClass().getDeclaredFields();
             for (Field field : fields) {
@@ -155,7 +189,11 @@
                 // TODO   绠¢亾鍙风┖杩斿洖淇℃伅
                 continue;
             }
-            // List瀛�->  鍠備笣鏈哄搴旂殑鏈虹粍锛堝 pipe01 pipe02 浠h〃1#銆�2#鍗锋帴鏈虹粍锛�
+            /**
+             * pipeList 瀛樻斁鈥滆鍠備笣鏈哄搴旂殑鏈虹粍瀛楁鍚嶁��
+             * - 渚嬪 pipe01銆乸ipe02 浠h〃 1#銆�2#鍗锋帴/鍖呰鏈虹粍
+             * - 鍚庣画浼氫粠 pipe01/pipe02 鎻愬彇鏈虹粍鍙� equNo锛屽苟鐢ㄤ簬鎷兼帴 key 鏌ヨ鍗锋帴/鍖呰琛�
+             */
             List<String> pipeList = new ArrayList<>();
             for (Map.Entry<String, String> entry : pipeRevMap.entrySet()) {
                 //fsNum绗笁浣嶆槸鍠備笣鏈哄簭鍙�
@@ -168,8 +206,12 @@
                 continue;
             }
 
-            // 鏍规嵁鍑烘枡寮�濮嬬粨鏉熸椂闂达紝鏌ヨ璇ユ煖鏂欏湪鍝嚑涓彮娆$敓浜�
-            List<MdShiftBo> distShiftList = calcShiftSpans(distimebegin, distimeend, mdShifts);
+            /**
+             * 鏍规嵁 [distimebegin, effectiveDistEnd] 璁$畻娑夊強鍒扮殑鐝鍒楄〃
+             * - 鍑烘枡宸茬粨鏉燂細effectiveDistEnd=distimeend
+             * - 鍑烘枡鏈粨鏉燂細effectiveDistEnd=now
+             */
+            List<MdShiftBo> distShiftList = calcShiftSpans(distimebegin, effectiveDistEnd, mdShifts);
             storeSilkInfoVo.setDistShiftList(distShiftList);
             if (distShiftList.isEmpty()) continue;
             //鏌ヨ鏃ユ湡鍜岀彮娆″唴鍗锋帴鏈虹粍鐨勪骇閲�
@@ -177,9 +219,12 @@
             // 鍗峰寘浜ч噺缁熻
             Double rollerOutput = 0.0;
             Double packerOutput = 0.0;
-            // 鏄庣粏鍒楄〃
+            // 鏄庣粏鍒楄〃锛堜粎瀛樻渶缁堟鏁扮粨鏋滐級
             List<StoreSilkDetailVo> rollerDetailList = new ArrayList<>();
             List<StoreSilkDetailVo> packerDetailList = new ArrayList<>();
+            // 鎿嶄綔璁板綍鍒楄〃锛堝瓨鎵�鏈夊鍑忚繃绋嬶級
+            List<StoreSilkDetailVo> rollerRecordList = new ArrayList<>();
+            List<StoreSilkDetailVo> packerRecordList = new ArrayList<>();
 
             for (int s = 0; s < distShiftList.size(); s++) {
                 MdShiftBo shiftBo = distShiftList.get(s);
@@ -189,24 +234,23 @@
                 String shift = shiftBo.getCode();
 
                 // 瑙f瀽鐝鏃堕棿
-                // 1. 鑾峰彇鐝閰嶇疆鐨勫紑濮嬪拰缁撴潫鏃堕棿瀛楃涓� (鏍煎紡濡� "07:30:00")
+                // 1) 鑾峰彇鐝閰嶇疆鐨勫紑濮�/缁撴潫鏃堕棿 (鍙兘鏄� "HH:mm" 鎴� "HH:mm:ss")
                 String stimStr = shiftBo.getStim();
                 String etimStr = shiftBo.getEtim();
                 if (StringUtils.isEmpty(stimStr) || StringUtils.isEmpty(etimStr)) {
                     continue;
                 }
-                // 2. 琛ュ叏绉掓暟锛堝鏋滈厤缃粎涓� HH:mm锛�
+                // 2) 琛ュ叏绉掓暟锛堝鏋滈厤缃粎涓� HH:mm锛�
                 if (stimStr.length() == 5) stimStr += ":00";
                 if (etimStr.length() == 5) etimStr += ":00";
 
-                // 3. 缁撳悎鏃ユ湡瑙f瀽涓� LocalDateTime
-                // 娉ㄦ剰锛歴hiftBo.getDay() 鏄鐝鐨勫綊灞炴棩鏈�
+                // 3) 缁撳悎鏃ユ湡锛坰hiftBo.getDay() 涓虹彮娆″綊灞炴棩锛夎В鏋愪负 LocalDateTime
                 String dateStr = shiftBo.getDay().toInstant().atZone(zone).toLocalDate().toString();
                 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                 LocalDateTime shiftStart = LocalDateTime.parse(dateStr + " " + stimStr, formatter);
                 LocalDateTime shiftEnd = LocalDateTime.parse(dateStr + " " + etimStr, formatter);
 
-                // 4. 澶勭悊璺ㄥぉ鐝锛氬鏋� 缁撴潫鏃堕棿 <= 寮�濮嬫椂闂达紝璇存槑璺ㄥぉ锛岀粨鏉熸椂闂撮渶 +1 澶�
+                // 4) 澶勭悊璺ㄥぉ鐝锛氬鏋� 缁撴潫鏃堕棿 <= 寮�濮嬫椂闂达紝璇存槑璺ㄥぉ锛岀粨鏉熸椂闂� +1 澶�
                 if (!shiftEnd.isAfter(shiftStart)) {
                     shiftEnd = shiftEnd.plusDays(1);
                 }
@@ -215,16 +259,43 @@
                 Date stimDate = Date.from(shiftStart.atZone(zone).toInstant());
                 Date etimDate = Date.from(shiftEnd.atZone(zone).toInstant());
 
-                // 璁$畻鐝缁撴潫鍓�10鍒嗛挓鐨勬椂闂寸偣
-                String shiftEndStr = shiftEnd.format(formatter);
-                String tenMinBeforeShiftEnd = shiftEnd.minusMinutes(10).format(formatter);
+                /**
+                 * 涓轰簡鍚屾椂鏀寔鈥滃嚭鏂欐湭缁撴潫鈥濓紝杩欓噷寮曞叆涓�涓�滄湰鐝鐨勭粺璁$獥鍙b�濓細
+                 *
+                 * 缁熻缁撴潫鏃跺埢 calcEnd = min(鐝缁撴潫, effectiveDistEnd)
+                 * - 鍑烘枡宸茬粨鏉燂細effectiveDistEnd=distimeend锛屽彲鑳芥棭浜庣彮娆$粨鏉燂紝calcEnd=distimeend
+                 * - 鍑烘枡鏈粨鏉燂細effectiveDistEnd=now锛宑alcEnd=now 鎴� 鐝缁撴潫锛堝彇杈冨皬锛�
+                 *
+                 * 缁熻寮�濮嬫椂鍒� calcStart = max(鐝寮�濮�, distimebegin)
+                 * - 鑻ュ嚭鏂欏紑濮嬫櫄浜庣彮娆″紑濮嬶紝鍒欎粠鍑烘枡寮�濮嬬粺璁�
+                 * - 鑻ュ嚭鏂欏紑濮嬫棭浜庣彮娆″紑濮嬶紝鍒欎粠鐝寮�濮嬬粺璁�
+                 *
+                 * 鏈�缁堟湰鐝鏈夋晥浜ч噺鍙e緞涓猴細
+                 *   output = Qty(calcEnd) - Qty(calcStart)
+                 *
+                 * 璇存槑锛氳繖涓彛寰勫凡缁忊�滈殣鍚簡鎵e熬鈥�
+                 * - 濡傛灉 calcEnd < 鐝缁撴潫锛堜緥濡傚嚭鏂欏凡缁撴潫鎴栫粺璁″埌褰撳墠鏃跺埢锛夛紝灏惧反鑷劧涓嶄細琚粺璁¤繘鍘�
+                 * - 鍥犳涓嶉渶瑕佸啀棰濆鍐欎竴涓�滄墸灏� if(...)鈥濆垎鏀紝閫昏緫鏇寸粺涓�銆佹洿涓嶅鏄撳嚭閿�
+                 */
+                LocalDateTime effectiveEndLdt = LocalDateTime.ofInstant(effectiveDistEnd.toInstant(), zone);
+                LocalDateTime calcEnd = shiftEnd.isBefore(effectiveEndLdt) ? shiftEnd : effectiveEndLdt;
+                Date calcEndDate = Date.from(calcEnd.atZone(zone).toInstant());
+                if (!calcEndDate.after(stimDate)) {
+                    continue;
+                }
+                Date calcStartDate = distimebegin.after(stimDate) ? distimebegin : stimDate;
+                if (!calcEndDate.after(calcStartDate)) {
+                    continue;
+                }
+                String calcEndStr = calcEnd.format(formatter);
+                String tenMinBeforeCalcEnd = calcEnd.minusMinutes(10).format(formatter);
 
                 // 鏍规嵁鍗锋帴鏈虹粍鍜岀彮娆¤幏鍙栦骇閲忥紙pipeList = 澶氬皯涓満缁勶級
                 for (int j = 0; j < pipeList.size(); j++) {
                     String pipe = pipeList.get(j);
                     // 鎻愬彇鏈虹粍鍙�
                     String equNo = pipe.replaceAll("\\D+", "");
-                    //绠¢亾鍙�
+                    // 绠¢亾鍙凤紙鐢ㄤ簬鏄庣粏灞曠ず锛夛細浠� feedMatch 鐨� pipe01/pipe02... 瀛楁鍊奸噷鍙栨湯浣�
                     String channel = pipeMap.get("pipe" + equNo);
                     if (channel != null && channel.length() > 0) {
                         channel = channel.substring(channel.length() - 1);
@@ -232,7 +303,12 @@
                         channel = "";
                     }
 
-                    //娉ㄦ剰4鍙风閬撲互鍚庡搴旂殑鏈虹粍闇�瑕�+1锛屾満缁�4鍙风┖缂鸿烦鍒�5鍙�
+                    /**
+                     * 鏈虹粍鍙锋槧灏勮鍒欙紙涓氬姟绾﹀畾锛夛細
+                     * - pipe04 瀵瑰簲鐨勬満缁勫彿鍦ㄧ郴缁熼噷鏄┖缂虹殑锛岄渶瑕佽烦鍒� 5 鍙�
+                     * - 鍥犳褰撶閬撳彿 >= 4 鏃讹紝鏈虹粍鍙烽渶瑕� +1
+                     * - 鍚屾椂杩欓噷琛ラ綈涓� 2 浣嶆暟瀛楋紝渚夸簬鎷� key锛堜緥濡� 01/02/05...锛�
+                     */
                     try {
                         int equ = Integer.parseInt(equNo);
                         equNo = String.format("%02d", equ >= 4 ? equ + 1 : equ);
@@ -243,18 +319,27 @@
                     }
 
 
-                    // 鎷兼帴鍗锋帴鏈虹殑key锛屼腑闂� "1" 浠h〃鍗锋帴鏈猴紝鏍煎紡锛氱彮娆� + "1" + 鏈虹粍鍙�
+                    // key 鎷兼帴瑙勫垯锛�
+                    // - 鍗锋帴鏈猴細鐝 + "1" + 鏈虹粍鍙凤紙渚嬪 101銆�105...锛�
                     String key = shift + "1" + equNo;
-                    // 鎷兼帴鍖呰鏈虹殑key锛屼腑闂� "2" 浠h〃鍖呰鏈猴紝鏍煎紡锛氱彮娆� + "2" + 鏈虹粍鍙�
+                    // - 鍖呰鏈猴細鐝 + "2" + 鏈虹粍鍙凤紙渚嬪 201銆�205...锛�
                     String packerKey = shift + "2" + equNo;
 
                     // ================= 鍗锋帴鏈轰骇閲忕粺璁� =================
                     Double currentRollerOutput = 0.0;
-                    // 1. 鏌ヨ鐝缁撴潫鏃剁殑浜ч噺蹇収
+                    /**
+                     * 鍙栨暟绛栫暐璇存槑锛堝嵎鎺�/鍖呰涓�鑷达級锛�
+                     * - 琛ㄥ唴鐨� qty 瑙嗕负绱鍊硷紙鍚屼竴 key 涓嬪崟璋冮�掑锛�
+                     * - 鐢变簬鏁版嵁鏄噰鏍蜂笂鎶ワ紝鏌愪釜鏃跺埢涓嶄竴瀹氬垰濂芥湁璁板綍
+                     * - 鍥犳閲囩敤鈥滅洰鏍囨椂鍒诲墠 10 鍒嗛挓鍐咃紝绂荤洰鏍囨渶杩戠殑涓�鏉¤褰曗�濅綔涓哄揩鐓у��
+                     *
+                     * 娉ㄦ剰锛�10鍒嗛挓鏄粡楠岀獥鍙o紝濡傛灉鐜板満閲囨牱鏇寸█鐤忥紝鍙�冭檻鏀惧绐楀彛
+                     */
+                    // 1) 鏌ヨ缁熻缁撴潫鏃跺埢 calcEnd 鐨勫揩鐓у�� Qty(calcEnd)
                     LambdaQueryWrapper<RollerTimeData> rlqw = new LambdaQueryWrapper<>();
-                    rlqw.le(RollerTimeData::getTime, shiftEndStr)
+                    rlqw.le(RollerTimeData::getTime, calcEndStr)
                             .eq(RollerTimeData::getKey, key)
-                            .ge(RollerTimeData::getTime, tenMinBeforeShiftEnd)
+                            .ge(RollerTimeData::getTime, tenMinBeforeCalcEnd)
                             .orderByDesc(RollerTimeData::getTime)
                             .isNotNull(RollerTimeData::getQty)
                             .gt(RollerTimeData::getQty, 0)
@@ -262,51 +347,55 @@
 
                     RollerTimeData rData = rollerTimeDataMapper.selectOne(rlqw);
                     if (rData != null) {
-                        // 鍒濆浜ч噺璁句负鐝缁撴潫鏃剁殑绱鍊�
+                        // 鍏堟妸缁熻缁撴潫鏃跺埢绱鍊煎姞杩涙潵锛歝urrent = Qty(calcEnd)
                         currentRollerOutput += rData.getQty();
 
-                        // 2. 澶勭悊鈥滄墸澶粹�濓細鍑烘枡寮�濮嬫椂闂� > 鐝寮�濮嬫椂闂�
-                        if (distimebegin.after(stimDate)) {
-                            LocalDateTime distBeginTime = LocalDateTime.ofInstant(distimebegin.toInstant(), zone);
-                            String distBeginStr = distBeginTime.format(formatter);
-                            String tenMinBeforeDistBegin = distBeginTime.minusMinutes(10).format(formatter);
+                        // 璁板綍杩囩▼锛氱彮娆℃埅姝㈢疮璁�
+                        StoreSilkDetailVo endRecord = new StoreSilkDetailVo();
+                        endRecord.setFsNum(fsNum.substring(2, 3));
+                        endRecord.setSiloNum(containerNum);
+                        endRecord.setPipeNum(channel);
+                        endRecord.setEquNo(equNo);
+                        endRecord.setShiftCode(shift);
+                        endRecord.setShiftStartTime(calcStartDate);
+                        endRecord.setShiftEndTime(calcEndDate);
+                        endRecord.setOutput(rData.getQty());
+                        endRecord.setCalcType("鐝鎴绱");
+                        endRecord.setHitTime(rData.getTime());
+                        rollerRecordList.add(endRecord);
+
+                        // 2) 鎵b�滃ご鈥濓細濡傛灉缁熻寮�濮嬫椂鍒绘櫄浜庣彮娆″紑濮嬶紝鍒欏噺鍘� Qty(calcStart)
+                        if (calcStartDate.after(stimDate)) {
+                            LocalDateTime calcStartLdt = LocalDateTime.ofInstant(calcStartDate.toInstant(), zone);
+                            String calcStartStr = calcStartLdt.format(formatter);
+                            String tenMinBeforeCalcStart = calcStartLdt.minusMinutes(10).format(formatter);
 
                             LambdaQueryWrapper<RollerTimeData> beginRlqw = new LambdaQueryWrapper<>();
-                            beginRlqw.le(RollerTimeData::getTime, distBeginStr)
-                                    .eq(RollerTimeData::getKey, key)
-                                    .ge(RollerTimeData::getTime, tenMinBeforeDistBegin)
-                                    .orderByDesc(RollerTimeData::getTime)
-                                    .isNotNull(RollerTimeData::getQty)
-                                    .gt(RollerTimeData::getQty, 0)
-                                    .last("LIMIT 1");
+                            beginRlqw.le(RollerTimeData::getTime, calcStartStr)
+                                .eq(RollerTimeData::getKey, key)
+                                .ge(RollerTimeData::getTime, tenMinBeforeCalcStart)
+                                .orderByDesc(RollerTimeData::getTime)
+                                .isNotNull(RollerTimeData::getQty)
+                                .gt(RollerTimeData::getQty, 0)
+                                .last("LIMIT 1");
 
                             RollerTimeData rBeginData = rollerTimeDataMapper.selectOne(beginRlqw);
                             if (rBeginData != null) {
                                 currentRollerOutput -= rBeginData.getQty();
-                            }
-                        }
 
-                        // 3. 澶勭悊鈥滄墸灏锯�濓細鍑烘枡缁撴潫鏃堕棿 < 鐝缁撴潫鏃堕棿
-                        if (etimDate.after(distimeend)) {
-                            LocalDateTime distEndTime = LocalDateTime.ofInstant(distimeend.toInstant(), zone);
-                            String distEndStr = distEndTime.format(formatter);
-                            String tenMinBeforeDistEnd = distEndTime.minusMinutes(10).format(formatter);
-
-                            LambdaQueryWrapper<RollerTimeData> endRlqw = new LambdaQueryWrapper<>();
-                            endRlqw.le(RollerTimeData::getTime, distEndStr)
-                                    .eq(RollerTimeData::getKey, key)
-                                    .ge(RollerTimeData::getTime, tenMinBeforeDistEnd)
-                                    .orderByDesc(RollerTimeData::getTime)
-                                    .isNotNull(RollerTimeData::getQty)
-                                    .gt(RollerTimeData::getQty, 0)
-                                    .last("LIMIT 1");
-
-                            RollerTimeData rEndData = rollerTimeDataMapper.selectOne(endRlqw);
-                            if (rEndData != null) {
-                                double qtyDelta = rData.getQty() - rEndData.getQty();
-                                if (qtyDelta > 0) {
-                                    currentRollerOutput -= qtyDelta;
-                                }
+                                // 璁板綍杩囩▼锛氭墸闄ゅご閮ㄤ骇閲�
+                                StoreSilkDetailVo beginRecord = new StoreSilkDetailVo();
+                                beginRecord.setFsNum(fsNum.substring(2, 3));
+                                beginRecord.setSiloNum(containerNum);
+                                beginRecord.setPipeNum(channel);
+                                beginRecord.setEquNo(equNo);
+                                beginRecord.setShiftCode(shift);
+                                beginRecord.setShiftStartTime(calcStartDate);
+                                beginRecord.setShiftEndTime(calcEndDate);
+                                beginRecord.setOutput(-rBeginData.getQty()); // 璐熸暟琛ㄧず鎵i櫎
+                                beginRecord.setCalcType("鎵i櫎鍑烘枡鍓嶇疮璁�");
+                                beginRecord.setHitTime(rBeginData.getTime());
+                                rollerRecordList.add(beginRecord);
                             }
                         }
                     }
@@ -320,71 +409,75 @@
                         detail.setPipeNum(channel);
                         detail.setEquNo(equNo);
                         detail.setShiftCode(shift);
-                        detail.setShiftStartTime(stimDate);
-                        detail.setShiftEndTime(etimDate);
+                        detail.setShiftStartTime(calcStartDate);
+                        detail.setShiftEndTime(calcEndDate);
                         detail.setOutput(currentRollerOutput);
                         rollerDetailList.add(detail);
                     }
 
                     // ================= 鍖呰鏈轰骇閲忕粺璁� =================
                     Double currentPackerOutput = 0.0;
-                    // 1. 鏌ヨ鐝缁撴潫鏃剁殑浜ч噺蹇収
+                    // 1) 鏌ヨ缁熻缁撴潫鏃跺埢 calcEnd 鐨勫揩鐓у�� Qty(calcEnd)
                     LambdaQueryWrapper<PackerTimeData> plqw = new LambdaQueryWrapper<>();
-                    plqw.le(PackerTimeData::getTime, shiftEndStr)
+                    plqw.le(PackerTimeData::getTime, calcEndStr)
                             .eq(PackerTimeData::getKey, packerKey)
-                            .ge(PackerTimeData::getTime, tenMinBeforeShiftEnd)
+                            .ge(PackerTimeData::getTime, tenMinBeforeCalcEnd)
                             .orderByDesc(PackerTimeData::getTime)
-                            .isNotNull(PackerTimeData::getQty)
-                            .gt(PackerTimeData::getQty, 0)
+                            .isNotNull(PackerTimeData::getTsQty)
+                            .gt(PackerTimeData::getTsQty, 0)
                             .last("LIMIT 1");
 
                     PackerTimeData pData = packerTimeDataMapper.selectOne(plqw);
                     if (pData != null) {
-                        // 鍒濆浜ч噺璁句负鐝缁撴潫鏃剁殑绱鍊�
-                        currentPackerOutput += pData.getQty();
+                        // 鍏堟妸缁熻缁撴潫鏃跺埢绱鍊煎姞杩涙潵锛歝urrent = Qty(calcEnd)
+                        currentPackerOutput += pData.getTsQty();
 
-                        // 2. 澶勭悊鈥滄墸澶粹��
-                        if (distimebegin.after(stimDate)) {
-                            LocalDateTime distBeginTime = LocalDateTime.ofInstant(distimebegin.toInstant(), zone);
-                            String distBeginStr = distBeginTime.format(formatter);
-                            String tenMinBeforeDistBegin = distBeginTime.minusMinutes(10).format(formatter);
+                        // 璁板綍杩囩▼锛氱彮娆℃埅姝㈢疮璁�
+                        StoreSilkDetailVo endRecord = new StoreSilkDetailVo();
+                        endRecord.setFsNum(fsNum.substring(2, 3));
+                        endRecord.setSiloNum(containerNum);
+                        endRecord.setPipeNum(channel);
+                        endRecord.setEquNo(equNo);
+                        endRecord.setShiftCode(shift);
+                        endRecord.setShiftStartTime(calcStartDate);
+                        endRecord.setShiftEndTime(calcEndDate);
+                        endRecord.setOutput(pData.getTsQty());
+                        endRecord.setCalcType("鐝鎴绱");
+                        endRecord.setHitTime(pData.getTime());
+                        packerRecordList.add(endRecord);
+
+                        // 2) 鎵b�滃ご鈥濓細濡傛灉缁熻寮�濮嬫椂鍒绘櫄浜庣彮娆″紑濮嬶紝鍒欏噺鍘� Qty(calcStart)
+                        if (calcStartDate.after(stimDate)) {
+                            LocalDateTime calcStartLdt = LocalDateTime.ofInstant(calcStartDate.toInstant(), zone);
+                            String calcStartStr = calcStartLdt.format(formatter);
+                            String tenMinBeforeCalcStart = calcStartLdt.minusMinutes(10).format(formatter);
 
                             LambdaQueryWrapper<PackerTimeData> beginPlqw = new LambdaQueryWrapper<>();
-                            beginPlqw.le(PackerTimeData::getTime, distBeginStr)
-                                    .eq(PackerTimeData::getKey, packerKey)
-                                    .ge(PackerTimeData::getTime, tenMinBeforeDistBegin)
-                                    .orderByDesc(PackerTimeData::getTime)
-                                    .isNotNull(PackerTimeData::getQty)
-                                    .gt(PackerTimeData::getQty, 0)
-                                    .last("LIMIT 1");
+                            beginPlqw.le(PackerTimeData::getTime, calcStartStr)
+                                .eq(PackerTimeData::getKey, packerKey)
+                                .ge(PackerTimeData::getTime, tenMinBeforeCalcStart)
+                                .orderByDesc(PackerTimeData::getTime)
+                                .isNotNull(PackerTimeData::getTsQty)
+                                .gt(PackerTimeData::getTsQty, 0)
+                                .last("LIMIT 1");
 
                             PackerTimeData pBeginData = packerTimeDataMapper.selectOne(beginPlqw);
                             if (pBeginData != null) {
-                                currentPackerOutput -= pBeginData.getQty();
-                            }
-                        }
+                                currentPackerOutput -= pBeginData.getTsQty();
 
-                        // 3. 澶勭悊鈥滄墸灏锯��
-                        if (etimDate.after(distimeend)) {
-                            LocalDateTime distEndTime = LocalDateTime.ofInstant(distimeend.toInstant(), zone);
-                            String distEndStr = distEndTime.format(formatter);
-                            String tenMinBeforeDistEnd = distEndTime.minusMinutes(10).format(formatter);
-
-                            LambdaQueryWrapper<PackerTimeData> endPlqw = new LambdaQueryWrapper<>();
-                            endPlqw.le(PackerTimeData::getTime, distEndStr)
-                                    .eq(PackerTimeData::getKey, packerKey)
-                                    .ge(PackerTimeData::getTime, tenMinBeforeDistEnd)
-                                    .orderByDesc(PackerTimeData::getTime)
-                                    .isNotNull(PackerTimeData::getQty)
-                                    .gt(PackerTimeData::getQty, 0)
-                                    .last("LIMIT 1");
-
-                            PackerTimeData pEndData = packerTimeDataMapper.selectOne(endPlqw);
-                            if (pEndData != null) {
-                                double qtyDelta = pData.getQty() - pEndData.getQty();
-                                if (qtyDelta > 0) {
-                                    currentPackerOutput -= qtyDelta;
-                                }
+                                // 璁板綍杩囩▼锛氭墸闄ゅご閮ㄤ骇閲�
+                                StoreSilkDetailVo beginRecord = new StoreSilkDetailVo();
+                                beginRecord.setFsNum(fsNum.substring(2, 3));
+                                beginRecord.setSiloNum(containerNum);
+                                beginRecord.setPipeNum(channel);
+                                beginRecord.setEquNo(equNo);
+                                beginRecord.setShiftCode(shift);
+                                beginRecord.setShiftStartTime(calcStartDate);
+                                beginRecord.setShiftEndTime(calcEndDate);
+                                beginRecord.setOutput(-pBeginData.getTsQty()); // 璐熸暟琛ㄧず鎵i櫎
+                                beginRecord.setCalcType("鎵i櫎鍑烘枡鍓嶇疮璁�");
+                                beginRecord.setHitTime(pBeginData.getTime());
+                                packerRecordList.add(beginRecord);
                             }
                         }
                     }
@@ -398,17 +491,20 @@
                         detail.setPipeNum(channel);
                         detail.setEquNo(equNo);
                         detail.setShiftCode(shift);
-                        detail.setShiftStartTime(stimDate);
-                        detail.setShiftEndTime(etimDate);
+                        detail.setShiftStartTime(calcStartDate);
+                        detail.setShiftEndTime(calcEndDate);
                         detail.setOutput(currentPackerOutput);
                         packerDetailList.add(detail);
                     }
                 }
             }
+            // 灏嗘眹鎬荤粨鏋滀笌鏄庣粏缁撴灉鍥炲啓鍒� StoreSilkInfoVo锛屼緵鍓嶇鍒楄〃/鎶藉眽鏄庣粏灞曠ず浣跨敤
             storeSilkInfoVo.setRollerOutput(rollerOutput);
             storeSilkInfoVo.setPackerOutput(packerOutput);
             storeSilkInfoVo.setRollerDetailList(rollerDetailList);
             storeSilkInfoVo.setPackerDetailList(packerDetailList);
+            storeSilkInfoVo.setRollerRecordList(rollerRecordList);
+            storeSilkInfoVo.setPackerRecordList(packerRecordList);
 
         }
 
@@ -523,11 +619,44 @@
         LambdaQueryWrapper<StoreSilkInfo> lqw = Wrappers.lambdaQuery();
         lqw.orderByAsc(StoreSilkInfo::getId);
         lqw.like(StringUtils.isNotBlank(bo.getMaterialname()), StoreSilkInfo::getMaterialname, bo.getMaterialname());
-        lqw.eq(StringUtils.isNotBlank(bo.getBatchcode()), StoreSilkInfo::getBatchcode, bo.getBatchcode());
-        lqw.eq(bo.getActualstarttime() != null, StoreSilkInfo::getActualstarttime, bo.getActualstarttime());
+        lqw.like(StringUtils.isNotBlank(bo.getBatchcode()), StoreSilkInfo::getBatchcode, bo.getBatchcode());
+        if (bo.getActualstarttime() != null) {
+            ZoneId zone = ZoneId.systemDefault();
+            LocalDate day = bo.getActualstarttime().toInstant().atZone(zone).toLocalDate();
+            Date dayStart = Date.from(day.atStartOfDay(zone).toInstant());
+            Date nextDayStart = Date.from(day.plusDays(1).atStartOfDay(zone).toInstant());
+            lqw.ge(StoreSilkInfo::getActualstarttime, dayStart);
+            lqw.lt(StoreSilkInfo::getActualstarttime, nextDayStart);
+        }
         lqw.eq(bo.getDistimebegin() != null, StoreSilkInfo::getDistimebegin, bo.getDistimebegin());
         lqw.eq(bo.getDistimeend() != null, StoreSilkInfo::getDistimeend, bo.getDistimeend());
-        lqw.eq(StringUtils.isNotBlank(bo.getSiloid()), StoreSilkInfo::getSiloid, bo.getSiloid());
+        if (StringUtils.isNotBlank(bo.getSiloid())) {
+            // 鏀寔澶氫釜鏌滃彿鏌ヨ锛屼互閫楀彿鍒嗛殧
+            String[] siloids = bo.getSiloid().split(",");
+            lqw.and(wrapper -> {
+                for (String val : siloids) {
+                    val = val.trim();
+                    if (StringUtils.isBlank(val)) {
+                        continue;
+                    }
+                    String finalVal = val;
+                    // 浣跨敤 OR 杩炴帴澶氫釜鏌滃彿鏉′欢
+                    wrapper.or(w -> {
+                        try {
+                            int num = Integer.parseInt(finalVal);
+                            String padded = String.format("%02d", num);
+                            // 鍖归厤 _1 鎴� _01 (鍏煎涓嶈ˉ闆跺拰琛ラ浂鐨勬儏鍐�)
+                            w.likeLeft(StoreSilkInfo::getSiloid, "_" + num)
+                                    .or()
+                                    .likeLeft(StoreSilkInfo::getSiloid, "_" + padded);
+                        } catch (NumberFormatException e) {
+                            // 闈炴暟瀛楀垯鎸夊師鍊煎尮閰�
+                            w.eq(StoreSilkInfo::getSiloid, finalVal);
+                        }
+                    });
+                }
+            });
+        }
         lqw.between(params.get("beginTime") != null && params.get("endTime") != null,
                 StoreSilkInfo::getDistimeend, params.get("beginTime"), params.get("endTime"));
         return lqw;

--
Gitblit v1.9.3