From bbf11a79fce0131aa95905c09b00f25e7696d20b Mon Sep 17 00:00:00 2001
From: lsh <lsh@163.com>
Date: 星期二, 21 十月 2025 16:53:13 +0800
Subject: [PATCH] *

---
 src/main/java/com/zy/asrs/task/handler/OrderToLineHandler.java    |   73 +++
 src/main/java/com/zy/asrs/utils/OptimizedLockerPacking3Utils.java |  737 ++++++++++++++++++++++++++++++++++++++
 src/main/java/com/zy/asrs/utils/param/ItemUtilParam.java          |   82 +++
 src/main/java/com/zy/asrs/task/handler/ArmRulesHandler.java       |   76 +++
 src/main/java/com/zy/asrs/controller/ApiLogController.java        |    6 
 src/main/webapp/views/apiLog/apiLog.html                          |    8 
 src/main/java/com/zy/common/config/ControllerResAdvice.java       |    1 
 src/main/java/com/zy/asrs/task/OrderToSortLineScheduler.java      |   17 
 src/main/java/com/zy/asrs/utils/MultiLockerOptimizerUtils.java    |   10 
 src/main/webapp/static/js/apiLog/apiLog.js                        |   23 
 src/main/java/com/zy/asrs/utils/ToSortLineUtils.java              |   67 ++-
 11 files changed, 1,009 insertions(+), 91 deletions(-)

diff --git a/src/main/java/com/zy/asrs/controller/ApiLogController.java b/src/main/java/com/zy/asrs/controller/ApiLogController.java
index 1e450a3..dbbb366 100644
--- a/src/main/java/com/zy/asrs/controller/ApiLogController.java
+++ b/src/main/java/com/zy/asrs/controller/ApiLogController.java
@@ -56,7 +56,11 @@
                 wrapper.ge(entry.getKey(), DateUtils.convert(dates[0]));
                 wrapper.le(entry.getKey(), DateUtils.convert(dates[1]));
             } else {
-                wrapper.like(entry.getKey(), val);
+                if (entry.getKey().equals("url")){
+                    wrapper.like(entry.getKey(), val).or().like("client_ip", val);
+                } else {
+                    wrapper.like(entry.getKey(), val);
+                }
             }
         }
     }
diff --git a/src/main/java/com/zy/asrs/task/OrderToSortLineScheduler.java b/src/main/java/com/zy/asrs/task/OrderToSortLineScheduler.java
index 3fae3ca..8786ba7 100644
--- a/src/main/java/com/zy/asrs/task/OrderToSortLineScheduler.java
+++ b/src/main/java/com/zy/asrs/task/OrderToSortLineScheduler.java
@@ -5,13 +5,10 @@
 import com.zy.asrs.entity.*;
 import com.zy.asrs.entity.param.OrderToLine;
 import com.zy.asrs.service.*;
-import com.zy.asrs.service.impl.OrderDetlServiceImpl;
 import com.zy.asrs.task.core.ReturnT;
 import com.zy.asrs.task.handler.OrderToLineHandler;
-import com.zy.asrs.utils.GroupedLockerOptimizerUtils;
-import com.zy.asrs.utils.OptimizedLockerPackingUtils;
-import com.zy.asrs.utils.OrderInAndOutUtil;
 import com.zy.asrs.utils.ToSortLineUtils;
+import com.zy.asrs.utils.param.ItemUtilParam;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -48,12 +45,10 @@
         for (String orderNo : orderNos) {
             try{
                 List<OrderDetlPakin> orderDetlPakinList = orderDetlPakinService.selectList(new EntityWrapper<OrderDetlPakin>().eq("order_no",orderNo));
-//                List<GroupedLockerOptimizerUtils.Item> items = new ArrayList<>();
                 if (orderDetlPakinList.size()<1){
                     continue;
                 }
-
-                List<OptimizedLockerPackingUtils.Item> items = new ArrayList<>();
+                List<ItemUtilParam.Item> items = new ArrayList<>();
                 for (OrderDetlPakin orderDetl:orderDetlPakinList){
                     Integer number =  basArmRulesService.getNumber(orderDetl.getWeight(),orderDetl.getVolume(),orderDetl.getManLength(),orderDetl.getWidth(),orderDetl.getHeight());
                     if (number == null) {
@@ -70,20 +65,18 @@
                     String name = ToSortLineUtils.MergerParameter(orderDetl.getMatnr(),orderDetl.getStandby1(),orderDetl.getStandby2());
                     int maxCapacity = number;
                     int stock = orderDetl.getAnfme().intValue();
-//                    items.add(new GroupedLockerOptimizerUtils.Item(name, maxCapacity, stock));
-                    items.add(new OptimizedLockerPackingUtils.Item(name, maxCapacity, stock));
+                    items.add(new ItemUtilParam.Item(name, maxCapacity, stock));
                 }
 
                 OrderToLine orderToLine = new OrderToLine();
                 orderToLine.setOrderNo(orderNo);  //鍗曟嵁缂栧彿
                 orderToLine.setCreateTime(System.currentTimeMillis());  //鍒涘缓鏃堕棿
-//                OrderToLine orderToLineR = ToSortLineUtils.GetOrderToLineGro(items, orderToLine);
-                OrderToLine orderToLineR = ToSortLineUtils.GetOrderToLineOpt(items, orderToLine);
+                OrderToLine orderToLineR = ToSortLineUtils.GetOrderToLine(items, orderToLine,"Opt3");
 
                 try{
                     ReturnT<String> returnT = orderToLineHandler.start(orderToLineR);
                     if (!returnT.isSuccess()) {
-                        log.error("涓嬪彂鍗曟嵁澶辫触===>"+ JSON.toJSON(orderToLineR));
+//                        log.error("涓嬪彂鍗曟嵁澶辫触===>"+ JSON.toJSON(orderToLineR));
                     } else {
                         try{
                             for (OrderToLine.MatList matList:orderToLineR.getMatList()){
diff --git a/src/main/java/com/zy/asrs/task/handler/ArmRulesHandler.java b/src/main/java/com/zy/asrs/task/handler/ArmRulesHandler.java
index 4b6fc1f..555f519 100644
--- a/src/main/java/com/zy/asrs/task/handler/ArmRulesHandler.java
+++ b/src/main/java/com/zy/asrs/task/handler/ArmRulesHandler.java
@@ -2,13 +2,12 @@
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
 import com.core.common.Cools;
 import com.core.common.DateUtils;
+import com.core.common.SpringUtils;
 import com.core.exception.CoolException;
-import com.zy.asrs.entity.BasArmRules;
-import com.zy.asrs.entity.DocType;
-import com.zy.asrs.entity.Order;
-import com.zy.asrs.entity.OrderDetl;
+import com.zy.asrs.entity.*;
 import com.zy.asrs.entity.param.ArmPrecomputeParam;
 import com.zy.asrs.service.ApiLogService;
 import com.zy.asrs.service.BasArmRulesService;
@@ -79,20 +78,40 @@
                     throw new CoolException("鑾峰彇鐮佸灈鏁伴噺澶辫触");
                 }
             } catch (Exception e) {
-                log.error("fail", e);
-                return FAIL.setMsg(e.getMessage());
+                try{
+                    log.error("fail==>鑾峰彇鐮佸灈鏁伴噺:"+e.getLocalizedMessage());
+                } catch (Exception e1){
+
+                }
+//                return FAIL.setMsg(e.getLocalizedMessage());
+                return FAIL;
+//                log.error("fail", e);
+//                return FAIL.setMsg(e.getMessage());
             } finally {
                 try {
-                    // 淇濆瓨鎺ュ彛鏃ュ織
-                    apiLogService.save(
-                            "鑾峰彇鐮佸灈鏁伴噺",
-                            URL + QuantityOfPalletizing,
-                            null,
-                            "127.0.0.1",
-                            JSON.toJSONString(armPrecomputeParam),
-                            response,
-                            success
-                    );
+
+                    if (success){
+                        // 淇濆瓨鎺ュ彛鏃ュ織
+                        apiLogService.save(
+                                "鑾峰彇鐮佸灈鏁伴噺",
+                                URL +"/"+ QuantityOfPalletizing,
+                                null,
+                                "127.0.0.1",
+                                JSON.toJSONString(armPrecomputeParam),
+                                response,
+                                success
+                        );
+                    } else {
+                        beforeBodyWriteCallApiLogSave(
+                                "鑾峰彇鐮佸灈鏁伴噺",
+                                URL +"/"+ QuantityOfPalletizing,
+                                null,
+                                "127.0.0.1",
+                                JSON.toJSONString(armPrecomputeParam),
+                                response,
+                                success
+                        );
+                    }
                 } catch (Exception e) { log.error("", e); }
             }
         }catch (Exception e){
@@ -100,5 +119,30 @@
         }
         return SUCCESS;
     }
+    public void beforeBodyWriteCallApiLogSave(String name, String url, String appkey, String ip, String request, String response, boolean success) {
+        ApiLog apiLog = apiLogService.selectOne(new EntityWrapper<ApiLog>()
+                .eq("namespace", name)
+                .eq("request", request)
+                .eq("response", response)
+                .eq("result", success? 1:0)
+                .orderBy("create_time", false)
+        );
 
+        if (!Cools.isEmpty(apiLog)){
+            long parseLong = Long.parseLong(apiLog.getTimestamp());
+            if (new Date().getTime()-parseLong<5*1000*60){
+                return;
+            }
+        }
+        // 淇濆瓨鎺ュ彛鏃ュ織
+        apiLogService.save(
+                name,
+                url,
+                appkey,
+                ip,
+                request,
+                response,
+                success
+        );
+    }
 }
diff --git a/src/main/java/com/zy/asrs/task/handler/OrderToLineHandler.java b/src/main/java/com/zy/asrs/task/handler/OrderToLineHandler.java
index 153f89d..9e017d2 100644
--- a/src/main/java/com/zy/asrs/task/handler/OrderToLineHandler.java
+++ b/src/main/java/com/zy/asrs/task/handler/OrderToLineHandler.java
@@ -2,7 +2,11 @@
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.core.common.Cools;
+import com.core.common.SpringUtils;
 import com.core.exception.CoolException;
+import com.zy.asrs.entity.ApiLog;
 import com.zy.asrs.entity.param.ArmPrecomputeParam;
 import com.zy.asrs.entity.param.OrderToLine;
 import com.zy.asrs.service.ApiLogService;
@@ -12,12 +16,14 @@
 import com.zy.asrs.task.AbstractHandler;
 import com.zy.asrs.task.core.ReturnT;
 import com.zy.common.utils.HttpHandler;
+import com.zy.common.utils.IpTools;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -61,20 +67,37 @@
                     throw new CoolException("涓嬪彂鍗曟嵁澶辫触");
                 }
             } catch (Exception e) {
-                log.error("fail", e);
-                return FAIL.setMsg(e.getMessage());
+                try{
+                    log.error("fail==>涓嬪彂鍗曟嵁鑷冲垎鎷g嚎:"+e.getLocalizedMessage());
+                } catch (Exception e1){
+
+                }
+//                return FAIL.setMsg(e.getLocalizedMessage());
+                return FAIL;
             } finally {
                 try {
-                    // 淇濆瓨鎺ュ彛鏃ュ織
-                    apiLogService.save(
-                            "涓嬪彂鍗曟嵁鑷冲垎鎷g嚎",
-                            URL + Path,
-                            null,
-                            "127.0.0.1",
-                            JSON.toJSONString(orderToline),
-                            response,
-                            success
-                    );
+                    if (success){
+                        // 淇濆瓨鎺ュ彛鏃ュ織
+                        apiLogService.save(
+                                "涓嬪彂鍗曟嵁鑷冲垎鎷g嚎",
+                                URL +"/"+ Path,
+                                null,
+                                "127.0.0.1",
+                                JSON.toJSONString(orderToline),
+                                response,
+                                success
+                        );
+                    } else {
+                        beforeBodyWriteCallApiLogSave(
+                                "涓嬪彂鍗曟嵁鑷冲垎鎷g嚎",
+                                URL +"/"+ Path,
+                                null,
+                                "127.0.0.1",
+                                JSON.toJSONString(orderToline),
+                                response,
+                                success
+                        );
+                    }
                 } catch (Exception e) { log.error("", e); }
             }
         }catch (Exception e){
@@ -82,4 +105,30 @@
         }
         return SUCCESS;
     }
+
+    public void beforeBodyWriteCallApiLogSave(String name, String url, String appkey, String ip, String request, String response, boolean success) {
+        ApiLog apiLog = apiLogService.selectOne(new EntityWrapper<ApiLog>()
+                .eq("namespace", name)
+                .eq("response", response)
+                .eq("result", success? 1:0)
+                .orderBy("create_time", false)
+        );
+
+        if (!Cools.isEmpty(apiLog)){
+            long parseLong = Long.parseLong(apiLog.getTimestamp());
+            if (new Date().getTime()-parseLong<5*1000*60){
+                return;
+            }
+        }
+        // 淇濆瓨鎺ュ彛鏃ュ織
+        apiLogService.save(
+                name,
+                url,
+                appkey,
+                ip,
+                request,
+                response,
+                success
+        );
+    }
 }
diff --git a/src/main/java/com/zy/asrs/utils/MultiLockerOptimizerUtils.java b/src/main/java/com/zy/asrs/utils/MultiLockerOptimizerUtils.java
index e0db69f..b72ade2 100644
--- a/src/main/java/com/zy/asrs/utils/MultiLockerOptimizerUtils.java
+++ b/src/main/java/com/zy/asrs/utils/MultiLockerOptimizerUtils.java
@@ -1,4 +1,7 @@
 package com.zy.asrs.utils;
+import com.core.common.SnowflakeIdWorker;
+import com.core.common.SpringUtils;
+
 import java.util.*;
 
 public class MultiLockerOptimizerUtils {
@@ -33,12 +36,19 @@
     static class Locker {
         int id;
         double remainingSpace;
+        long bindingTags;
         Map<String, Integer> contents;
+        Set<String> itemTypes;
 
         public Locker(int id) {
             this.id = id;
             this.remainingSpace = 1.0;
             this.contents = new HashMap<>();
+            this.itemTypes = new HashSet<>();
+            SnowflakeIdWorker snowflakeIdWorker = SpringUtils.getBean(SnowflakeIdWorker.class);
+//            this.bindingTags = System.currentTimeMillis();
+            this.bindingTags = snowflakeIdWorker.nextId();
+
         }
 
         // 灏濊瘯鏀惧叆鐗╁搧
diff --git a/src/main/java/com/zy/asrs/utils/OptimizedLockerPacking3Utils.java b/src/main/java/com/zy/asrs/utils/OptimizedLockerPacking3Utils.java
new file mode 100644
index 0000000..c7f12dd
--- /dev/null
+++ b/src/main/java/com/zy/asrs/utils/OptimizedLockerPacking3Utils.java
@@ -0,0 +1,737 @@
+package com.zy.asrs.utils;
+
+import com.core.common.SnowflakeIdWorker;
+import com.core.common.SpringUtils;
+
+import java.util.*;
+
+public class OptimizedLockerPacking3Utils {
+
+    public static class Item {
+        String name;
+        double unitSpace;
+        int maxCapacity;
+        int stock;
+        int allocated; // 鏀逛负宸插垎閰嶆暟閲忥紝閬垮厤鐩存帴淇敼remaining瀵艰嚧鐨勬贩涔�
+
+        public Item(String name, int maxCapacity, int stock) {
+            this.name = name;
+            this.maxCapacity = maxCapacity;
+            this.unitSpace = 1.0 / maxCapacity;
+            this.stock = stock;
+            this.allocated = 0;
+        }
+
+        public int getRemaining() {
+            return stock - allocated;
+        }
+
+        public boolean allocate(int quantity) {
+            if (allocated + quantity <= stock) {
+                allocated += quantity;
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return name + "(鍗曟斁" + maxCapacity + "涓�, 搴撳瓨" + stock + "涓�)";
+        }
+    }
+
+    static class Locker {
+        int id;
+        double remainingSpace;
+        long bindingTags;
+        Map<String, Integer> contents;
+        Set<String> itemTypes;
+
+        public Locker(int id) {
+            this.id = id;
+            this.remainingSpace = 1.0;
+            this.contents = new HashMap<>();
+            this.itemTypes = new HashSet<>();
+            SnowflakeIdWorker snowflakeIdWorker = SpringUtils.getBean(SnowflakeIdWorker.class);
+            this.bindingTags = snowflakeIdWorker.nextId();
+        }
+
+        public boolean canAdd(Item item, int quantity) {
+            return remainingSpace >= quantity * item.unitSpace;
+        }
+
+        public boolean addItem(Item item, int quantity) {
+            // 楠岃瘉鍒嗛厤鏁伴噺
+            if (!item.allocate(quantity)) {
+                return false;
+            }
+
+            double spaceUsed = quantity * item.unitSpace;
+            if (spaceUsed > remainingSpace + 1e-6) {
+                // 鍥炴粴鍒嗛厤
+                item.allocated -= quantity;
+                return false;
+            }
+
+            remainingSpace -= spaceUsed;
+            contents.put(item.name, contents.getOrDefault(item.name, 0) + quantity);
+            itemTypes.add(item.name);
+            return true;
+        }
+
+        public boolean containsItemType(String itemName) {
+            return itemTypes.contains(itemName);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("鍌ㄧ墿鏌�").append(id).append(": ");
+            sb.append(String.format("鍓╀綑绌洪棿%.4f", remainingSpace)).append("\n");
+            for (Map.Entry<String, Integer> entry : contents.entrySet()) {
+                sb.append("  ").append(entry.getKey()).append(": ").append(entry.getValue()).append("涓猏n");
+            }
+            return sb.toString();
+        }
+    }
+
+    static class PackingSolution {
+        List<Locker> lockers;
+        int totalLockersUsed;
+        double overallUtilization;
+        int itemTypeChanges;
+        int pureLockers;
+
+        public PackingSolution() {
+            this.lockers = new ArrayList<>();
+        }
+
+        public void addLocker(Locker locker) {
+            lockers.add(locker);
+            totalLockersUsed = lockers.size();
+        }
+
+        public void calculateMetrics() {
+            double totalUsedSpace = 0;
+            itemTypeChanges = 0;
+            pureLockers = 0;
+            String lastItemType = null;
+
+            for (Locker locker : lockers) {
+                totalUsedSpace += (1.0 - locker.remainingSpace);
+
+                if (locker.itemTypes.size() == 1) {
+                    pureLockers++;
+                }
+
+                for (String itemType : locker.itemTypes) {
+                    if (lastItemType != null && !lastItemType.equals(itemType)) {
+                        itemTypeChanges++;
+                    }
+                    lastItemType = itemType;
+                }
+            }
+
+            overallUtilization = totalUsedSpace / totalLockersUsed;
+        }
+
+        @Override
+        public String toString() {
+            calculateMetrics();
+            StringBuilder sb = new StringBuilder();
+            sb.append("=== 浼樺寲鎽嗘斁鏂规 ===\n");
+            sb.append("浣跨敤鐨勫偍鐗╂煖鏁伴噺: ").append(totalLockersUsed).append("涓猏n");
+            sb.append("绾绫诲偍鐗╂煖: ").append(pureLockers).append("涓猏n");
+            sb.append("骞冲潎绌洪棿鍒╃敤鐜�: ").append(String.format("%.2f", overallUtilization * 100)).append("%\n");
+            sb.append("鐗╁搧绉嶇被鍒囨崲娆℃暟: ").append(itemTypeChanges).append("娆n\n");
+
+            List<Locker> pureLockersList = new ArrayList<>();
+            List<Locker> mixedLockersList = new ArrayList<>();
+
+            for (Locker locker : lockers) {
+                if (locker.itemTypes.size() == 1) {
+                    pureLockersList.add(locker);
+                } else {
+                    mixedLockersList.add(locker);
+                }
+            }
+
+            sb.append("銆愮函绉嶇被鍌ㄧ墿鏌溿��:\n");
+            for (Locker locker : pureLockersList) {
+                sb.append(locker.toString()).append("\n");
+            }
+
+            sb.append("銆愭贩鍚堝偍鐗╂煖銆�:\n");
+            for (Locker locker : mixedLockersList) {
+                sb.append(locker.toString()).append("\n");
+            }
+
+            return sb.toString();
+        }
+    }
+
+    /**
+     * 浣欐枡鐗╁搧杈呭姪绫�
+     */
+    private static class RemainderItem {
+        Item item;
+        int quantity;
+
+        RemainderItem(Item item, int quantity) {
+            this.item = item;
+            this.quantity = quantity;
+        }
+
+        @Override
+        public String toString() {
+            return item.name + "(" + quantity + "涓�)";
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null || getClass() != obj.getClass()) return false;
+            RemainderItem that = (RemainderItem) obj;
+            return quantity == that.quantity && item.name.equals(that.item.name);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(item.name, quantity);
+        }
+    }
+
+    public static void main(String[] args) {
+        Scanner scanner = new Scanner(System.in);
+
+        System.out.println("璇疯緭鍏ョ墿鍝佺绫绘暟閲�:");
+        int itemTypes = scanner.nextInt();
+        scanner.nextLine();
+
+        List<Item> items = new ArrayList<>();
+
+        for (int i = 0; i < itemTypes; i++) {
+            System.out.println("\n璇疯緭鍏ョ" + (i + 1) + "绉嶇墿鍝佺殑淇℃伅:");
+            System.out.print("鐗╁搧鍚嶇О: ");
+            String name = scanner.nextLine();
+
+            System.out.print("鍗曠瀛樻斁鏈�澶ф暟閲�: ");
+            int maxCapacity = scanner.nextInt();
+
+            System.out.print("搴撳瓨鏁伴噺: ");
+            int stock = scanner.nextInt();
+            scanner.nextLine();
+
+            items.add(new Item(name, maxCapacity, stock));
+        }
+
+        PackingSolution solution = optimizedPacking(items);
+        System.out.println("\n" + solution);
+
+        scanner.close();
+    }
+
+    /**
+     * 浼樺寲瑁呯绠楁硶锛氫慨澶嶆暟閲忕鐞嗛棶棰�
+     */
+    public static PackingSolution optimizedPacking(List<Item> items) {
+        // 楠岃瘉杈撳叆
+        if (items == null || items.isEmpty()) {
+            throw new IllegalArgumentException("鐗╁搧鍒楄〃涓嶈兘涓虹┖");
+        }
+
+        // 鍒涘缓鐗╁搧鍓湰鐢ㄤ簬澶勭悊
+        List<Item> itemsToPack = new ArrayList<>();
+        for (Item item : items) {
+            itemsToPack.add(new Item(item.name, item.maxCapacity, item.stock));
+        }
+
+        PackingSolution solution = new PackingSolution();
+        int lockerId = 1;
+
+        // 绗竴闃舵锛氬姣忕鐗╁搧杩涜闆嗕腑澶勭悊锛屽垎閰嶅畬鏁村偍鐗╂煖
+        Map<String, Integer> remainders = new HashMap<>();
+
+        for (Item item : itemsToPack) {
+            if (item.getRemaining() == 0) continue;
+
+            int fullLockersNeeded = item.getRemaining() / item.maxCapacity;
+            int remainder = item.getRemaining() % item.maxCapacity;
+
+            // 鍒嗛厤瀹屾暣鍌ㄧ墿鏌�
+            for (int i = 0; i < fullLockersNeeded; i++) {
+                Locker locker = new Locker(lockerId++);
+                if (locker.addItem(item, item.maxCapacity)) {
+                    solution.addLocker(locker);
+                } else {
+                    System.out.println("璀﹀憡: 鏃犳硶鍒嗛厤瀹屾暣鍌ㄧ墿鏌滅粰鐗╁搧 " + item.name);
+                }
+            }
+
+            if (remainder > 0) {
+                remainders.put(item.name, remainder);
+            }
+        }
+
+        // 绗簩闃舵锛氫紭鍖栦綑鏂欏垎閰�
+        if (!remainders.isEmpty()) {
+            uniformRemainderProcessing(remainders, itemsToPack, solution, lockerId);
+        }
+
+        // 楠岃瘉缁撴灉
+        if (!validateSolution(items, solution)) {
+            System.out.println("璀﹀憡: 鏁伴噺鍒嗛厤楠岃瘉澶辫触");
+        }
+
+        return solution;
+    }
+
+    /**
+     * 淇鍚庣殑鍧囧寑浣欐枡澶勭悊绠楁硶
+     */
+    private static void uniformRemainderProcessing(Map<String, Integer> remainders,
+                                                   List<Item> items,
+                                                   PackingSolution solution,
+                                                   int startLockerId) {
+        int lockerId = startLockerId;
+
+        // 灏嗕綑鏂欒浆鎹负鍙鐞嗙殑鐗╁搧鍒楄〃
+        List<RemainderItem> remainderItems = new ArrayList<>();
+        for (Item item : items) {
+            Integer remainder = remainders.get(item.name);
+            if (remainder != null && remainder > 0 && item.getRemaining() > 0) {
+                remainderItems.add(new RemainderItem(item, Math.min(remainder, item.getRemaining())));
+            }
+        }
+
+        // 鎸夌墿鍝佸崟浣嶇┖闂翠粠澶у埌灏忔帓搴�
+        remainderItems.sort((a, b) -> Double.compare(b.item.unitSpace, a.item.unitSpace));
+
+        // 浣跨敤淇鍚庣殑浣欐枡澶勭悊绠楁硶
+        List<Locker> remainderLockers = fixedRemainderArrangement(remainderItems, solution, lockerId);
+
+        // 灏嗘渶浼樿В娣诲姞鍒拌В鍐虫柟妗堜腑
+        for (Locker locker : remainderLockers) {
+            solution.addLocker(locker);
+        }
+    }
+
+    /**
+     * 淇鍚庣殑浣欐枡鎺掑垪鏂规
+     */
+    private static List<Locker> fixedRemainderArrangement(List<RemainderItem> remainderItems,
+                                                          PackingSolution solution,
+                                                          int startLockerId) {
+        if (remainderItems.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // 鍒涘缓鍓湰閬垮厤淇敼鍘熷鏁版嵁
+        List<RemainderItem> remaining = new ArrayList<>();
+        for (RemainderItem ri : remainderItems) {
+            if (ri.quantity > 0) {
+                remaining.add(new RemainderItem(ri.item, ri.quantity));
+            }
+        }
+
+        List<Locker> lockers = new ArrayList<>();
+        int lockerId = startLockerId;
+
+        // 涓昏绛栫暐锛氬垱寤洪珮鍒╃敤鐜囧偍鐗╂煖
+        while (!remaining.isEmpty()) {
+            Locker locker = createOptimizedLocker(remaining, lockerId);
+            if (locker != null) {
+                lockers.add(locker);
+                lockerId++;
+
+                // 绉婚櫎宸插鐞嗗畬鐨勭墿鍝�
+                Iterator<RemainderItem> iterator = remaining.iterator();
+                while (iterator.hasNext()) {
+                    RemainderItem ri = iterator.next();
+                    if (ri.quantity == 0) {
+                        iterator.remove();
+                    }
+                }
+
+                double utilization = (1.0 - locker.remainingSpace) * 100;
+                System.out.println("鍒涘缓鍌ㄧ墿鏌滐紝鍒╃敤鐜�: " + String.format("%.2f", utilization) + "%");
+            } else {
+                break;
+            }
+        }
+
+        // 澶勭悊鍓╀綑鐗╁搧锛堝鏋滄湁锛�
+        if (!remaining.isEmpty()) {
+            System.out.println("浣跨敤鏍囧噯绠楁硶澶勭悊鍓╀綑 " + remaining.size() + " 绉嶇墿鍝�");
+            List<Locker> standardLockers = standardBestFit(remaining, lockerId);
+            lockers.addAll(standardLockers);
+        }
+
+        return lockers;
+    }
+
+    /**
+     * 鍒涘缓浼樺寲鍌ㄧ墿鏌滐紙淇鏁伴噺楠岃瘉锛�
+     */
+    private static Locker createOptimizedLocker(List<RemainderItem> remaining, int lockerId) {
+        if (remaining.isEmpty()) {
+            return null;
+        }
+
+        Locker locker = new Locker(lockerId);
+        double targetUtilization = 0.85;
+        double minUtilization = 0.3; // 鏈�浣庡埄鐢ㄧ巼闃堝��
+
+        // 瀵绘壘鏈�浣崇粍鍚�
+        List<RemainderItem> bestCombination = findValidCombination(remaining, targetUtilization);
+
+        if (bestCombination.isEmpty()) {
+            // 灏濊瘯杈惧埌鏈�浣庡埄鐢ㄧ巼
+            bestCombination = findMinUtilizationCombination(remaining, minUtilization);
+        }
+
+        if (bestCombination.isEmpty()) {
+            return null;
+        }
+
+        // 鍒嗛厤缁勫悎鍒板偍鐗╂煖
+        boolean success = allocateValidCombination(remaining, locker, bestCombination);
+
+        if (!success || locker.contents.isEmpty()) {
+            return null;
+        }
+
+        // 妫�鏌ュ埄鐢ㄧ巼鏄惁鍙帴鍙�
+        double utilization = 1.0 - locker.remainingSpace;
+        if (utilization < minUtilization) {
+            // 鍥炴粴鍒嗛厤
+            rollbackAllocation(remaining, locker);
+            return null;
+        }
+
+        return locker;
+    }
+
+    /**
+     * 瀵绘壘鏈夋晥缁勫悎锛堜慨澶嶆暟閲忛獙璇侊級
+     */
+    private static List<RemainderItem> findValidCombination(List<RemainderItem> items, double targetUtilization) {
+        List<RemainderItem> bestCombination = new ArrayList<>();
+        double[] bestDiff = {Double.MAX_VALUE};
+
+        // 杩囨护鏈夋晥鐗╁搧
+        List<RemainderItem> availableItems = new ArrayList<>();
+        for (RemainderItem ri : items) {
+            if (ri.quantity > 0 && ri.item.getRemaining() > 0) {
+                availableItems.add(ri);
+            }
+        }
+
+        if (availableItems.isEmpty()) {
+            return bestCombination;
+        }
+
+        // 浣跨敤DFS鎼滅储鏈夋晥缁勫悎
+        validDfsCombination(availableItems, 0, 0.0, targetUtilization,
+                new ArrayList<>(), bestCombination, bestDiff);
+
+        return bestCombination;
+    }
+
+    /**
+     * 鏈夋晥鐨凞FS缁勫悎鎼滅储
+     */
+    private static void validDfsCombination(List<RemainderItem> items, int index, double currentSpace,
+                                            double targetUtilization,
+                                            List<RemainderItem> current,
+                                            List<RemainderItem> bestCombination, double[] bestDiff) {
+        // 妫�鏌ュ綋鍓嶇粍鍚堢殑鏈夋晥鎬�
+        if (!current.isEmpty()) {
+            double diff = Math.abs(currentSpace - targetUtilization);
+            if (currentSpace <= 1.0 + 1e-6 && diff < bestDiff[0] && isCombinationValid(current)) {
+                bestCombination.clear();
+                for (RemainderItem ri : current) {
+                    bestCombination.add(new RemainderItem(ri.item, ri.quantity));
+                }
+                bestDiff[0] = diff;
+
+                if (diff < 0.01) {
+                    return;
+                }
+            }
+        }
+
+        if (index >= items.size() || currentSpace > 1.0 + 1e-6) {
+            return;
+        }
+
+        RemainderItem currentItem = items.get(index);
+
+        // 涓嶉�夋嫨褰撳墠鐗╁搧
+        validDfsCombination(items, index + 1, currentSpace, targetUtilization,
+                current, bestCombination, bestDiff);
+
+        // 閫夋嫨褰撳墠鐗╁搧
+        if (currentItem.quantity > 0) {
+            int maxCanAdd = Math.min(currentItem.quantity,
+                    (int) Math.floor((1.0 - currentSpace) / currentItem.item.unitSpace));
+            maxCanAdd = Math.min(maxCanAdd, currentItem.item.getRemaining()); // 閲嶈淇锛氫笉瓒呰繃鍓╀綑鏁伴噺
+
+            for (int qty = 1; qty <= maxCanAdd; qty++) {
+                current.add(new RemainderItem(currentItem.item, qty));
+                validDfsCombination(items, index + 1, currentSpace + qty * currentItem.item.unitSpace,
+                        targetUtilization, current, bestCombination, bestDiff);
+                current.remove(current.size() - 1);
+            }
+        }
+    }
+
+    /**
+     * 妫�鏌ョ粍鍚堟槸鍚︽湁鏁堬紙淇鏁伴噺楠岃瘉锛�
+     */
+    private static boolean isCombinationValid(List<RemainderItem> combination) {
+        Map<String, Integer> totalQuantities = new HashMap<>();
+
+        for (RemainderItem ri : combination) {
+            int currentTotal = totalQuantities.getOrDefault(ri.item.name, 0);
+            totalQuantities.put(ri.item.name, currentTotal + ri.quantity);
+
+            // 妫�鏌ユ槸鍚﹁秴杩囩墿鍝佸墿浣欐暟閲�
+            if (currentTotal + ri.quantity > getRemainingQuantity(ri.item)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * 鑾峰彇鐗╁搧鍓╀綑鏁伴噺
+     */
+    private static int getRemainingQuantity(Item item) {
+        return item.stock - item.allocated;
+    }
+
+    /**
+     * 瀵绘壘杈惧埌鏈�浣庡埄鐢ㄧ巼鐨勭粍鍚�
+     */
+    private static List<RemainderItem> findMinUtilizationCombination(List<RemainderItem> items, double minUtilization) {
+        List<RemainderItem> combination = new ArrayList<>();
+        double currentSpace = 0.0;
+
+        // 鎸夊崟浣嶇┖闂存帓搴�
+        List<RemainderItem> sortedItems = new ArrayList<>(items);
+        sortedItems.sort((a, b) -> Double.compare(b.item.unitSpace, a.item.unitSpace));
+
+        for (RemainderItem ri : sortedItems) {
+            if (ri.quantity > 0 && currentSpace < minUtilization) {
+                int maxCanAdd = Math.min(ri.quantity,
+                        (int) Math.floor((1.0 - currentSpace) / ri.item.unitSpace));
+                maxCanAdd = Math.min(maxCanAdd, ri.item.getRemaining()); // 閲嶈淇
+
+                if (maxCanAdd > 0) {
+                    combination.add(new RemainderItem(ri.item, maxCanAdd));
+                    currentSpace += maxCanAdd * ri.item.unitSpace;
+                }
+            }
+        }
+
+        if (currentSpace >= minUtilization) {
+            return combination;
+        }
+
+        return new ArrayList<>();
+    }
+
+    /**
+     * 鍒嗛厤鏈夋晥缁勫悎鍒板偍鐗╂煖锛堜慨澶嶆暟閲忛獙璇侊級
+     */
+    private static boolean allocateValidCombination(List<RemainderItem> remaining, Locker locker,
+                                                    List<RemainderItem> combination) {
+        // 楠岃瘉缁勫悎涓殑鎵�鏈夌墿鍝侀兘鏈夎冻澶熺殑鏁伴噺
+        for (RemainderItem combItem : combination) {
+            boolean found = false;
+            for (RemainderItem remItem : remaining) {
+                if (remItem.item.name.equals(combItem.item.name)) {
+                    found = true;
+                    if (combItem.quantity > remItem.quantity) {
+                        return false;
+                    }
+                    if (combItem.quantity > remItem.item.getRemaining()) {
+                        return false;
+                    }
+                    break;
+                }
+            }
+            if (!found) {
+                return false;
+            }
+        }
+
+        // 瀹為檯鍒嗛厤
+        for (RemainderItem combItem : combination) {
+            for (RemainderItem remItem : remaining) {
+                if (remItem.item.name.equals(combItem.item.name)) {
+                    if (locker.addItem(combItem.item, combItem.quantity)) {
+                        remItem.quantity -= combItem.quantity;
+                    } else {
+                        return false;
+                    }
+                    break;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * 鍥炴粴鍒嗛厤
+     */
+    private static void rollbackAllocation(List<RemainderItem> remaining, Locker locker) {
+        for (Map.Entry<String, Integer> entry : locker.contents.entrySet()) {
+            String itemName = entry.getKey();
+            int quantity = entry.getValue();
+
+            for (RemainderItem ri : remaining) {
+                if (ri.item.name.equals(itemName)) {
+                    ri.quantity += quantity;
+                    ri.item.allocated -= quantity; // 鍥炴粴鍒嗛厤鏁伴噺
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * 鏍囧噯鏈�浣抽�傚簲绠楁硶
+     */
+    private static List<Locker> standardBestFit(List<RemainderItem> remainderItems, int startLockerId) {
+        List<Locker> lockers = new ArrayList<>();
+        int lockerId = startLockerId;
+
+        // 鍒涘缓鍓湰
+        List<RemainderItem> remaining = new ArrayList<>();
+        for (RemainderItem ri : remainderItems) {
+            if (ri.quantity > 0) {
+                remaining.add(new RemainderItem(ri.item, ri.quantity));
+            }
+        }
+
+        // 鎸夊崟浣嶇┖闂存帓搴�
+        remaining.sort((a, b) -> Double.compare(b.item.unitSpace, a.item.unitSpace));
+
+        for (RemainderItem ri : remaining) {
+            while (ri.quantity > 0 && ri.item.getRemaining() > 0) {
+                Locker bestLocker = null;
+                double bestRemainingSpace = Double.MAX_VALUE;
+
+                // 瀵绘壘鏈�浣冲偍鐗╂煖
+                for (Locker locker : lockers) {
+                    if (locker.canAdd(ri.item, 1) && locker.remainingSpace < bestRemainingSpace) {
+                        bestLocker = locker;
+                        bestRemainingSpace = locker.remainingSpace;
+                    }
+                }
+
+                if (bestLocker != null) {
+                    int maxCanAdd = (int) Math.floor(bestLocker.remainingSpace / ri.item.unitSpace);
+                    int actualAdd = Math.min(ri.quantity, maxCanAdd);
+                    actualAdd = Math.min(actualAdd, ri.item.getRemaining()); // 閲嶈淇
+
+                    if (actualAdd > 0 && bestLocker.addItem(ri.item, actualAdd)) {
+                        ri.quantity -= actualAdd;
+                    } else {
+                        break;
+                    }
+                } else {
+                    // 鍒涘缓鏂板偍鐗╂煖
+                    Locker newLocker = new Locker(lockerId++);
+                    int maxCanAdd = (int) Math.floor(1.0 / ri.item.unitSpace);
+                    int actualAdd = Math.min(ri.quantity, maxCanAdd);
+                    actualAdd = Math.min(actualAdd, ri.item.getRemaining()); // 閲嶈淇
+
+                    if (actualAdd > 0 && newLocker.addItem(ri.item, actualAdd)) {
+                        lockers.add(newLocker);
+                        ri.quantity -= actualAdd;
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
+
+        return lockers;
+    }
+
+    /**
+     * 楠岃瘉瑙e喅鏂规锛堜慨澶嶉獙璇侀�昏緫锛�
+     */
+    private static boolean validateSolution(List<Item> originalItems, PackingSolution solution) {
+        Map<String, Integer> allocatedQuantities = new HashMap<>();
+        Map<String, Integer> originalQuantities = new HashMap<>();
+
+        // 璁板綍鍘熷鏁伴噺
+        for (Item item : originalItems) {
+            originalQuantities.put(item.name, item.stock);
+        }
+
+        // 璁$畻鍒嗛厤鏁伴噺
+        for (Locker locker : solution.lockers) {
+            for (Map.Entry<String, Integer> entry : locker.contents.entrySet()) {
+                String itemName = entry.getKey();
+                int quantity = entry.getValue();
+                allocatedQuantities.put(itemName, allocatedQuantities.getOrDefault(itemName, 0) + quantity);
+            }
+        }
+
+        boolean valid = true;
+        for (Map.Entry<String, Integer> entry : originalQuantities.entrySet()) {
+            String itemName = entry.getKey();
+            int originalQty = entry.getValue();
+            int allocatedQty = allocatedQuantities.getOrDefault(itemName, 0);
+
+            if (originalQty != allocatedQty) {
+                System.out.println("楠岃瘉澶辫触: " + itemName + " 鍘熷鏁伴噺=" + originalQty +
+                        ", 鍒嗛厤鏁伴噺=" + allocatedQty);
+                valid = false;
+            }
+        }
+
+        if (valid) {
+            System.out.println("鏁伴噺楠岃瘉閫氳繃");
+        }
+
+        return valid;
+    }
+
+    /**
+     * 鎬ц兘娴嬭瘯鍜屾瘮杈�
+     */
+    public static void performanceTest() {
+        System.out.println("=== 鎬ц兘娴嬭瘯 ===");
+
+        // 娴嬭瘯鏁版嵁
+        List<Item> testItems = Arrays.asList(
+                new Item("X", 20, 87),
+                new Item("Y", 15, 63),
+                new Item("Z", 34, 125),
+                new Item("T", 25, 48),
+                new Item("U", 40, 92)
+        );
+
+        System.out.println("娴嬭瘯鐗╁搧鏁伴噺: " + testItems.size());
+        int totalItems = testItems.stream().mapToInt(item -> item.stock).sum();
+        System.out.println("鎬荤墿鍝佹暟閲�: " + totalItems);
+
+        long startTime = System.currentTimeMillis();
+        PackingSolution solution = optimizedPacking(testItems);
+        long endTime = System.currentTimeMillis();
+
+        System.out.println("\n浼樺寲绠楁硶缁撴灉:");
+        System.out.println("澶勭悊鏃堕棿: " + (endTime - startTime) + "ms");
+        System.out.println("鍌ㄧ墿鏌滄暟閲�: " + solution.totalLockersUsed);
+        System.out.println("绾绫诲偍鐗╂煖: " + solution.pureLockers);
+        System.out.println("绌洪棿鍒╃敤鐜�: " + String.format("%.2f", solution.overallUtilization * 100) + "%");
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/zy/asrs/utils/ToSortLineUtils.java b/src/main/java/com/zy/asrs/utils/ToSortLineUtils.java
index 7195635..f2b5c46 100644
--- a/src/main/java/com/zy/asrs/utils/ToSortLineUtils.java
+++ b/src/main/java/com/zy/asrs/utils/ToSortLineUtils.java
@@ -1,7 +1,7 @@
 package com.zy.asrs.utils;
 
-import com.zy.asrs.entity.OrderDetl;
 import com.zy.asrs.entity.param.OrderToLine;
+import com.zy.asrs.utils.param.ItemUtilParam;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -36,34 +36,29 @@
         return sku+sign_F+po+sign_F+upc;
     }
 
-    public static OrderToLine GetOrderToLineGro(List<GroupedLockerOptimizerUtils.Item> items,OrderToLine orderToLine){
-        List<OrderToLine.MatList> matLists = new ArrayList<>();
-        // 浣跨敤鍒嗙粍浼樺厛绠楁硶
-        GroupedLockerOptimizerUtils.PackingSolution solution = GroupedLockerOptimizerUtils.packItemsWithGrouping(items);
-        for (GroupedLockerOptimizerUtils.Locker locker:solution.lockers) {
-            for (String mantnr : locker.contents.keySet()){
-                System.out.println(mantnr+"<===>"+locker.contents.get(mantnr));
-                String[] split = mantnr.split(Pattern.quote(sign_F));
-                OrderToLine.MatList mat = new OrderToLine.MatList(
-                        split[0],  // matnr -> sku
-                        split[1],  //  supp -> po -> s1
-                        locker.contents.get(mantnr).doubleValue(),   //鏁存枡
-                        split[2],   //barcode -> upc -> s2
-                        1,
-                        null,   //origin -> supplier 璐ф簮
-                        locker.bindingTags
-                );
-                matLists.add(mat);
-            }
+    public static OrderToLine GetOrderToLine(List<ItemUtilParam.Item> items, OrderToLine orderToLine,String sign){
+        switch (sign){
+            case "Opt":
+                List<OptimizedLockerPackingUtils.Item> itemsOpt = new ArrayList<>();
+                for (ItemUtilParam.Item item:items){
+                    itemsOpt.add(new OptimizedLockerPackingUtils.Item(item.getName(),item.getMaxCapacity(),item.getStock()));
+                }
+                return GetOrderToLineOpt(itemsOpt,orderToLine);
+            case "Opt3":
+                List<OptimizedLockerPacking3Utils.Item> itemsOpt3 = new ArrayList<>();
+                for (ItemUtilParam.Item item:items){
+                    itemsOpt3.add(new OptimizedLockerPacking3Utils.Item(item.getName(),item.getMaxCapacity(),item.getStock()));
+                }
+                return GetOrderToLineOpt3(itemsOpt3,orderToLine);
+            default:
+                return null;
         }
-        orderToLine.setMatList(matLists);
-        return orderToLine;
     }
-
     public static OrderToLine GetOrderToLineOpt(List<OptimizedLockerPackingUtils.Item> items,OrderToLine orderToLine){
         List<OrderToLine.MatList> matLists = new ArrayList<>();
         // 浣跨敤鍒嗙粍浼樺厛绠楁硶
         OptimizedLockerPackingUtils.PackingSolution packingSolution = OptimizedLockerPackingUtils.optimizedPacking(items);
+//        System.out.println("\n" + packingSolution);
         for (OptimizedLockerPackingUtils.Locker locker:packingSolution.lockers) {
             for (String mantnr : locker.contents.keySet()){
                 System.out.println(mantnr+"<===>"+locker.contents.get(mantnr));
@@ -83,4 +78,30 @@
         orderToLine.setMatList(matLists);
         return orderToLine;
     }
+
+    public static OrderToLine GetOrderToLineOpt3(List<OptimizedLockerPacking3Utils.Item> items,OrderToLine orderToLine){
+        List<OrderToLine.MatList> matLists = new ArrayList<>();
+        // 浣跨敤鍒嗙粍浼樺厛绠楁硶
+        OptimizedLockerPacking3Utils.PackingSolution packingSolution = OptimizedLockerPacking3Utils.optimizedPacking(items);
+//        System.out.println("\n" + packingSolution);
+        for (OptimizedLockerPacking3Utils.Locker locker:packingSolution.lockers) {
+            for (String mantnr : locker.contents.keySet()){
+//                System.out.println(mantnr+"<===>"+locker.contents.get(mantnr));
+                String[] split = mantnr.split(Pattern.quote(sign_F));
+                OrderToLine.MatList mat = new OrderToLine.MatList(
+                        split[0],  // matnr -> sku
+                        split[1],  //  supp -> po -> s1
+                        locker.contents.get(mantnr).doubleValue(),   //鏁存枡
+                        split[2],   //barcode -> upc -> s2
+                        1,
+                        null,   //origin -> supplier 璐ф簮
+                        locker.bindingTags
+                );
+                matLists.add(mat);
+            }
+        }
+        orderToLine.setMatList(matLists);
+        return orderToLine;
+    }
+
 }
diff --git a/src/main/java/com/zy/asrs/utils/param/ItemUtilParam.java b/src/main/java/com/zy/asrs/utils/param/ItemUtilParam.java
index 4ca44df..39c799c 100644
--- a/src/main/java/com/zy/asrs/utils/param/ItemUtilParam.java
+++ b/src/main/java/com/zy/asrs/utils/param/ItemUtilParam.java
@@ -2,24 +2,78 @@
 
 import lombok.Data;
 
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
 @Data
 public class ItemUtilParam {
-    String name;
-    double unitSpace;
-    int maxCapacity;
-    int stock;
-    int remaining;
 
-    public ItemUtilParam(String name, int maxCapacity, int stock) {
-        this.name = name;
-        this.maxCapacity = maxCapacity;
-        this.unitSpace = 1.0 / maxCapacity;
-        this.stock = stock;
-        this.remaining = stock;
+    @Data
+    public static class Item {
+        String name;
+        double unitSpace;
+        int maxCapacity;
+        int stock;
+        int remaining;
+
+        public Item(String name, int maxCapacity, int stock) {
+            this.name = name;
+            this.maxCapacity = maxCapacity;
+            this.unitSpace = 1.0 / maxCapacity;
+            this.stock = stock;
+            this.remaining = stock;
+        }
+
+        @Override
+        public String toString() {
+            return name + "(鍗曟斁" + maxCapacity + "涓�, 搴撳瓨" + stock + "涓�)";
+        }
     }
 
-    @Override
-    public String toString() {
-        return name + "(鍗曟斁" + maxCapacity + "涓�, 搴撳瓨" + stock + "涓�)";
+
+    static class Locker {
+        int id;
+        double remainingSpace;
+        long bindingTags;
+        Map<String, Integer> contents;
+        Set<String> itemTypes;
+
+        public Locker(int id) {
+            this.id = id;
+            this.remainingSpace = 1.0;
+            this.contents = new HashMap<>();
+            this.itemTypes = new HashSet<>();
+            this.bindingTags = System.currentTimeMillis();
+
+        }
+
+        public boolean canAdd(ItemUtilParam.Item item, int quantity) {
+            return remainingSpace >= quantity * item.unitSpace;
+        }
+
+        public void addItem(ItemUtilParam.Item item, int quantity) {
+            double spaceUsed = quantity * item.unitSpace;
+            remainingSpace -= spaceUsed;
+            contents.put(item.name, contents.getOrDefault(item.name, 0) + quantity);
+            itemTypes.add(item.name);
+            item.remaining -= quantity;
+        }
+
+        public boolean containsItemType(String itemName) {
+            return itemTypes.contains(itemName);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("鍌ㄧ墿鏌�").append(id).append(": ");
+            sb.append(String.format("鍓╀綑绌洪棿%.4f", remainingSpace)).append("\n");
+            for (Map.Entry<String, Integer> entry : contents.entrySet()) {
+                sb.append("  ").append(entry.getKey()).append(": ").append(entry.getValue()).append("涓猏n");
+            }
+            return sb.toString();
+        }
     }
 }
diff --git a/src/main/java/com/zy/common/config/ControllerResAdvice.java b/src/main/java/com/zy/common/config/ControllerResAdvice.java
index ba399ec..4f603c4 100644
--- a/src/main/java/com/zy/common/config/ControllerResAdvice.java
+++ b/src/main/java/com/zy/common/config/ControllerResAdvice.java
@@ -85,7 +85,6 @@
 
         ApiLog apiLog = apiLogService.selectOne(new EntityWrapper<ApiLog>()
                 .eq("namespace", name)
-                .eq("request", request)
                 .eq("response", response)
                 .eq("result", success? 1:0)
                 .orderBy("create_time", false)
diff --git a/src/main/webapp/static/js/apiLog/apiLog.js b/src/main/webapp/static/js/apiLog/apiLog.js
index 1d24b5e..947f693 100644
--- a/src/main/webapp/static/js/apiLog/apiLog.js
+++ b/src/main/webapp/static/js/apiLog/apiLog.js
@@ -21,24 +21,25 @@
         cellMinWidth: 50,
         height: 'full-120',
         cols: [[
-            {type: 'checkbox'}
+            // {type: 'checkbox'}
             // ,{field: 'id', align: 'center',title: 'ID'}
             // ,{field: 'uuid', align: 'center',title: '鏃ュ織缂栧彿'}
-            ,{field: 'namespace', align: 'center',title: '鍚嶇О绌洪棿'}
-            ,{field: 'url', align: 'center',title: '琛ㄥ崟ID'}
+            // ,
+            {field: 'namespace', align: 'center',title: '鍚嶇О绌洪棿',hide: false}
+            ,{field: 'url', align: 'center',title: '鎺ュ彛鍦板潃',hide: false}
             ,{field: 'appkey', align: 'center',title: '骞冲彴瀵嗛挜',hide: true}
-            // ,{field: 'timestamp', align: 'center',title: '鏃堕棿鎴�'}
-            ,{field: 'clientIp', align: 'center',title: 'URL',hide: true}
-            ,{field: 'request', align: 'center',title: '璇锋眰鍐呭'}
-            ,{field: 'response', align: 'center',title: '鎿嶄綔鍐呭'}
-            // ,{field: 'err', align: 'center',title: '寮傚父鍐呭'}
-            ,{field: 'result$', align: 'center',title: '缁撴灉', templet: '#resTpl', width: 80}
+            ,{field: 'timestamp', align: 'center',title: '鏃堕棿鎴�',hide: true}
+            ,{field: 'clientIp', align: 'center',title: '瀹㈡埛绔疘P',hide: false}
+            ,{field: 'request', align: 'center',title: '璇锋眰鍐呭',hide: false}
+            ,{field: 'response', align: 'center',title: '鎿嶄綔鍐呭',hide: false}
+            // ,{field: 'err', align: 'center',title: '寮傚父鍐呭',hide: true}
+            ,{field: 'result$', align: 'center',title: '缁撴灉', templet: '#resTpl', width: 80,hide: false}
             // ,{field: 'status$', align: 'center',title: '鐘舵��'}
-            ,{field: 'createTime$', align: 'center',title: '娣诲姞鏃堕棿'}
+            ,{field: 'createTime$', align: 'center',title: '娣诲姞鏃堕棿',hide: false}
             // ,{field: 'updateTime$', align: 'center',title: '淇敼鏃堕棿'}
             ,{field: 'memo', align: 'center',title: '澶囨敞', hide: true}
 
-            ,{fixed: 'right', title:'鎿嶄綔', align: 'center', toolbar: '#operate', width: 80}
+            ,{fixed: 'right', title:'鎿嶄綔', align: 'center', toolbar: '#operate', width: 80, hide: true}
         ]],
         request: {
             pageName: 'curr',
diff --git a/src/main/webapp/views/apiLog/apiLog.html b/src/main/webapp/views/apiLog/apiLog.html
index e35b6a9..132658e 100644
--- a/src/main/webapp/views/apiLog/apiLog.html
+++ b/src/main/webapp/views/apiLog/apiLog.html
@@ -24,6 +24,12 @@
                         </div>
                     </div>
                     <div class="layui-inline">
+                        <label class="layui-form-label">鎺ュ彛鍦板潃: </label>
+                        <div class="layui-input-inline">
+                            <input class="layui-input" type="text" name="url" placeholder="璇疯緭鍏ユ帴鍙e湴鍧�" autocomplete="off">
+                        </div>
+                    </div>
+                    <div class="layui-inline">
                         <label class="layui-form-label">璇锋眰鍐呭:</label>
                         <div class="layui-input-inline">
                             <input class="layui-input" type="text" name="request" placeholder="璇疯緭鍏ワ紙璁㈠崟鍙锋垨鍝佸彿锛�" autocomplete="off">
@@ -47,7 +53,7 @@
 <script type="text/html" id="toolbar">
     <div class="layui-btn-container">
 <!--        <button class="layui-btn layui-btn-sm" id="btn-add" lay-event="addData">鏂板</button>-->
-        <button class="layui-btn layui-btn-sm layui-btn-danger" id="btn-delete" lay-event="deleteData">鍒犻櫎</button>
+<!--        <button class="layui-btn layui-btn-sm layui-btn-danger" id="btn-delete" lay-event="deleteData">鍒犻櫎</button>-->
         <button class="layui-btn layui-btn-primary layui-btn-sm" id="btn-export" lay-event="exportData" style="float: right">瀵煎嚭</button>
     </div>
 </script>

--
Gitblit v1.9.1