From a1334287fc3e563ff3494553d0c1e6fa390b314d Mon Sep 17 00:00:00 2001
From: cl <1442464845@qq.com>
Date: 星期二, 24 三月 2026 16:54:44 +0800
Subject: [PATCH] 大屏缓存

---
 src/main/webapp/views/wrkMast/wrkMast.html                    |    2 
 src/main/java/com/zy/common/utils/RedisUtil.java              |  202 +++++++++++++++++++++++++++++++++++++--
 src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java   |   57 ++++++++++-
 src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java |    7 -
 src/main/webapp/views/errorWrkMast/errorWrkMast.html          |    2 
 5 files changed, 246 insertions(+), 24 deletions(-)

diff --git a/src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
index e5b2d2c..267615a 100644
--- a/src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
@@ -26,10 +26,7 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 
 /**
  * 绉诲姩绔湇鍔℃牳蹇冪被
@@ -634,7 +631,7 @@
     @Transactional
     public void createEmptyWrk(String barcode, Long userId) {
         WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("barcode", barcode));
-        if (!Cools.isEmpty(wrkMast)){
+        if (!Cools.isEmpty(wrkMast)&& !Objects.isNull(wrkMast.getWrkSts())&&!wrkMast.getWrkSts().equals(15L)){
             throw new CoolException("鎵樼洏缂栧彿" + barcode + "宸插瓨鍦ㄥ伐浣滄。");
         }
         List<WaitPakin> waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", barcode));
diff --git a/src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
index 1fe34d1..d96111d 100644
--- a/src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -21,6 +21,8 @@
 import com.zy.common.properties.SlaveProperties;
 import com.zy.common.service.CommonService;
 import com.zy.common.web.WcsController;
+import com.zy.asrs.task.core.ReturnT;
+import com.zy.asrs.task.handler.WorkMastHandler;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -80,6 +82,8 @@
     private WaitPakinService waitPakinService;
     @Autowired
     private MonitorLocMapCacheService monitorLocMapCacheService;
+    @Autowired
+    private WorkMastHandler workMastHandler;
 
     @Override
     @Transactional
@@ -609,14 +613,18 @@
         if (Cools.isEmpty(wrkMast)){
             throw new CoolException(workNo+"宸ヤ綔妗d笉瀛樺湪");
         }
-        if (wrkMast.getWrkSts() == 4 || wrkMast.getWrkSts() == 14) {
+        long sts = wrkMast.getWrkSts();
+        if (sts == 4 || sts == 5 || sts == 14 || sts == 15 || sts == 20) {
             throw new CoolException("褰撳墠宸ヤ綔妗e凡瀹屾垚");
         }
-        // 鍏ュ簱 + 搴撲綅杞Щ
-        if (wrkMast.getWrkSts() < 4 || (wrkMast.getWrkSts() > 10 && wrkMast.getIoType()==11)) {
+        boolean inboundFinish = wrkMast.getWrkSts() < 4 || (wrkMast.getWrkSts() > 10 && wrkMast.getIoType() != null && wrkMast.getIoType() == 11);
+        boolean outboundFinish = wrkMast.getWrkSts() > 10 && (wrkMast.getIoType() == null || wrkMast.getIoType() != 11);
+        if (!inboundFinish && !outboundFinish) {
+            throw new CoolException("褰撳墠宸ヤ綔鐘舵�佹棤娉曟墜鍔ㄥ畬鎴�");
+        }
+        if (inboundFinish) {
             wrkMast.setWrkSts(4L);
-        // 鍑哄簱
-        } else if (wrkMast.getWrkSts() > 10) {
+        } else {
             wrkMast.setWrkSts(14L);
         }
         Date now = new Date();
@@ -624,8 +632,45 @@
         wrkMast.setCrnEndTime(now);
         wrkMast.setModiTime(now);
         wrkMast.setModiUser(userId);
-        // 瀹屾垚鎿嶄綔浜哄憳璁板綍
         wrkMast.setManuType("鎵嬪姩瀹屾垚");
+        ReturnT<String> rt = workMastHandler.start(wrkMast);
+        if (!rt.isSuccess()) {
+            throw new CoolException(Cools.isEmpty(rt.getMsg()) ? "瀹屾垚澶勭悊澶辫触" : rt.getMsg());
+        }
+        // doOut 瀵� 103/107 涓嶈惤 15 鏃讹紝鎵嬪姩琛ラ綈 15锛涙簮搴撲綅 O 涓庡畾鏃朵换鍔� doOut 涓�鑷�
+        if (wrkMast.getWrkSts() == 14) {
+            wrkMast.setWrkSts(15L);
+            wrkMast.setModiTime(now);
+            wrkMast.setModiUser(userId);
+            if (!Cools.isEmpty(wrkMast.getSourceLocNo())) {
+                LocMast src = locMastService.selectById(wrkMast.getSourceLocNo());
+                if (!Cools.isEmpty(src) && !"O".equals(src.getLocSts())) {
+                    Integer io = wrkMast.getIoType();
+                    if (io != null && (io == 101 || io == 110)) {
+                        src.setLocSts("O");
+                        src.setModiTime(now);
+                        src.setIoTime(now);
+                        src.setModiUser(userId);
+                        if (!locMastService.updateById(src)) {
+                            throw new CoolException("鏇存柊婧愬簱浣嶇姸鎬佸け璐�");
+                        }
+                    } else if ("R".equals(src.getLocSts())) {
+                        src.setLocSts("O");
+                        src.setModiTime(now);
+                        src.setIoTime(now);
+                        src.setModiUser(userId);
+                        if (!locMastService.updateById(src)) {
+                            throw new CoolException("鏇存柊婧愬簱浣嶇姸鎬佸け璐�");
+                        }
+                    }
+                }
+            }
+        }
+        wrkMast.setManuType("鎵嬪姩瀹屾垚");
+        wrkMast.setModiUser(userId);
+        wrkMast.setCrnStrTime(DateUtils.calculate(now, 1L, TimeUnit.SECONDS, true));
+        wrkMast.setCrnEndTime(now);
+        wrkMast.setModiTime(now);
         if (!wrkMastService.updateById(wrkMast)) {
             throw new CoolException("淇敼宸ヤ綔妗eけ璐�");
         }
diff --git a/src/main/java/com/zy/common/utils/RedisUtil.java b/src/main/java/com/zy/common/utils/RedisUtil.java
index dd3e607..6464c68 100644
--- a/src/main/java/com/zy/common/utils/RedisUtil.java
+++ b/src/main/java/com/zy/common/utils/RedisUtil.java
@@ -1,15 +1,21 @@
 package com.zy.common.utils;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
 
 /**
  * redisTemplate灏佽
@@ -18,11 +24,21 @@
 @Component
 public class RedisUtil {
 
+    private static final Logger log = LoggerFactory.getLogger(RedisUtil.class);
+
+    private static final long LOCAL_NO_EXPIRE = Long.MAX_VALUE;
+    private static final long LOCAL_DEFAULT_TTL_SEC = 86400L;
+
 //    @Autowired
 //    private RedisTemplate<String, Object> redisTemplate;
 
     @Autowired
     private RedisTemplate redisTemplate;
+
+    private final ConcurrentHashMap<String, LocalCacheEntry> localCache = new ConcurrentHashMap<>();
+    private final Object fallbackLock = new Object();
+    private volatile boolean redisFallbackMode = false;
+    private final Set<String> fallbackLocalKeys = ConcurrentHashMap.newKeySet();
 
     public RedisUtil(RedisTemplate redisTemplate) {
         this.redisTemplate = redisTemplate;
@@ -65,10 +81,13 @@
      */
     public boolean hasKey(String key) {
         try {
-            return redisTemplate.hasKey(key);
+            boolean ok = redisTemplate.hasKey(key);
+            notifyRedisAvailable();
+            return ok;
         } catch (Exception e) {
-            e.printStackTrace();
-            return false;
+            enterFallbackIfNeeded();
+            log.info("Redis 涓嶅彲鐢紝浠� JVM 鍐呭瓨鍒ゆ柇 hasKey锛宬ey={}锛屽師鍥�: {}", key, e.getMessage());
+            return localHasValid(key);
         }
     }
 
@@ -80,10 +99,24 @@
     @SuppressWarnings("unchecked")
     public void del(String... key) {
         if (key != null && key.length > 0) {
-            if (key.length == 1) {
-                redisTemplate.delete(key[0]);
-            } else {
-                redisTemplate.delete(CollectionUtils.arrayToList(key));
+            try {
+                if (key.length == 1) {
+                    redisTemplate.delete(key[0]);
+                } else {
+                    redisTemplate.delete(CollectionUtils.arrayToList(key));
+                }
+                notifyRedisAvailable();
+            } catch (Exception e) {
+                enterFallbackIfNeeded();
+                log.warn("Redis 涓嶅彲鐢紝鍒犻櫎鏃� Redis 澶辫触锛屼粎娓呯悊鏈湴锛屽師鍥�: {}", e.getMessage());
+            }
+            for (String k : key) {
+                if (k != null) {
+                    localCache.remove(k);
+                    synchronized (fallbackLock) {
+                        fallbackLocalKeys.remove(k);
+                    }
+                }
             }
         }
     }
@@ -97,7 +130,18 @@
      * @return 鍊�
      */
     public Object get(String key) {
-        return key == null ? null : redisTemplate.opsForValue().get(key);
+        if (key == null) {
+            return null;
+        }
+        try {
+            Object v = redisTemplate.opsForValue().get(key);
+            notifyRedisAvailable();
+            return v;
+        } catch (Exception e) {
+            enterFallbackIfNeeded();
+            log.info("Redis 涓嶅彲鐢紝浠� JVM 鍐呭瓨璇诲彇 key={}锛屽師鍥�: {}", key, e.getMessage());
+            return localGet(key);
+        }
     }
 
     /**
@@ -125,10 +169,13 @@
     public boolean set(String key, Object value) {
         try {
             redisTemplate.opsForValue().set(key, value);
+            localCache.remove(key);
+            notifyRedisAvailable();
             return true;
         } catch (Exception e) {
-            e.printStackTrace();
-            return false;
+            log.debug("Redis set 澶辫触", e);
+            localPutFallback(key, value, LOCAL_DEFAULT_TTL_SEC);
+            return true;
         }
     }
 
@@ -146,11 +193,16 @@
                 redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
             } else {
                 set(key, value);
+                return true;
             }
+            localCache.remove(key);
+            notifyRedisAvailable();
             return true;
         } catch (Exception e) {
-            e.printStackTrace();
-            return false;
+            log.debug("Redis set(expire) 澶辫触", e);
+            long ttl = time > 0 ? time : LOCAL_DEFAULT_TTL_SEC;
+            localPutFallback(key, value, ttl);
+            return true;
         }
     }
 
@@ -598,7 +650,15 @@
      * @return
      */
     public Set keys(String pattern) {
-        return redisTemplate.keys(pattern);
+        try {
+            Set<?> s = redisTemplate.keys(pattern);
+            notifyRedisAvailable();
+            return s;
+        } catch (Exception e) {
+            enterFallbackIfNeeded();
+            log.info("Redis 涓嶅彲鐢紝浠� JVM 鍐呭瓨鍖归厤 keys锛宲attern={}锛屽師鍥�: {}", pattern, e.getMessage());
+            return localKeysMatching(pattern);
+        }
     }
 
     /**
@@ -611,6 +671,122 @@
         redisTemplate.convertAndSend(channel, message);
     }
 
+    private void enterFallbackIfNeeded() {
+        synchronized (fallbackLock) {
+            if (!redisFallbackMode) {
+                redisFallbackMode = true;
+                log.warn("Redis 涓嶅彲鐢紝瀛楃涓茬浉鍏崇紦瀛樺皢鏆傚瓨浜� JVM 鍐呭瓨锛屽緟 Redis 鎭㈠鍚庤嚜鍔ㄥ垏鍥� Redis 骞舵竻鐞嗕笂杩伴敭");
+            }
+        }
+    }
+
+    private void notifyRedisAvailable() {
+        if (!redisFallbackMode && fallbackLocalKeys.isEmpty()) {
+            return;
+        }
+        synchronized (fallbackLock) {
+            if (!redisFallbackMode && fallbackLocalKeys.isEmpty()) {
+                return;
+            }
+            int n = fallbackLocalKeys.size();
+            for (String k : new ArrayList<>(fallbackLocalKeys)) {
+                localCache.remove(k);
+            }
+            fallbackLocalKeys.clear();
+            redisFallbackMode = false;
+            if (n > 0) {
+                log.info("Redis 宸叉仮澶嶏紝宸叉竻鐞� JVM 鍐呭瓨涓� {} 涓洜 Redis 涓嶅彲鐢ㄨ�屾殏瀛樼殑閿�", n);
+            } else {
+                log.info("Redis 宸叉仮澶�");
+            }
+        }
+    }
+
+    private void localPutFallback(String key, Object value, long ttlSeconds) {
+        if (key == null) {
+            return;
+        }
+        synchronized (fallbackLock) {
+            if (!redisFallbackMode) {
+                redisFallbackMode = true;
+                log.warn("Redis 涓嶅彲鐢紝瀛楃涓茬浉鍏崇紦瀛樺皢鏆傚瓨浜� JVM 鍐呭瓨锛屽緟 Redis 鎭㈠鍚庤嚜鍔ㄥ垏鍥� Redis 骞舵竻鐞嗕笂杩伴敭");
+            }
+            fallbackLocalKeys.add(key);
+            localPut(key, value, ttlSeconds);
+        }
+        log.info("Redis 涓嶅彲鐢紝閿凡鍐欏叆 JVM 鍐呭瓨: {}", key);
+    }
+
+    private void localPut(String key, Object value, long ttlSeconds) {
+        if (key == null) {
+            return;
+        }
+        long expireAt = ttlSeconds > 0
+                ? System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(ttlSeconds)
+                : LOCAL_NO_EXPIRE;
+        localCache.put(key, new LocalCacheEntry(value, expireAt));
+    }
+
+    private Object localGet(String key) {
+        LocalCacheEntry e = localCache.get(key);
+        if (e == null) {
+            return null;
+        }
+        if (e.expireAtMillis != LOCAL_NO_EXPIRE && System.currentTimeMillis() > e.expireAtMillis) {
+            localCache.remove(key, e);
+            return null;
+        }
+        return e.value;
+    }
+
+    private boolean localHasValid(String key) {
+        return localGet(key) != null;
+    }
+
+    private Set<String> localKeysMatching(String pattern) {
+        if (pattern == null) {
+            return new HashSet<>();
+        }
+        Pattern p = Pattern.compile(globToRegex(pattern));
+        Set<String> out = new HashSet<>();
+        for (String k : localCache.keySet()) {
+            if (localGet(k) == null) {
+                continue;
+            }
+            if (p.matcher(k).matches()) {
+                out.add(k);
+            }
+        }
+        return out;
+    }
+
+    private static String globToRegex(String glob) {
+        StringBuilder sb = new StringBuilder("^");
+        for (int i = 0; i < glob.length(); i++) {
+            char c = glob.charAt(i);
+            if (c == '*') {
+                sb.append(".*");
+            } else if (c == '?') {
+                sb.append('.');
+            } else if ("\\.[]{}()+-^$|".indexOf(c) >= 0) {
+                sb.append('\\').append(c);
+            } else {
+                sb.append(c);
+            }
+        }
+        sb.append('$');
+        return sb.toString();
+    }
+
+    private static final class LocalCacheEntry {
+        final Object value;
+        final long expireAtMillis;
+
+        LocalCacheEntry(Object value, long expireAtMillis) {
+            this.value = value;
+            this.expireAtMillis = expireAtMillis;
+        }
+    }
 
 }
 
diff --git a/src/main/webapp/views/errorWrkMast/errorWrkMast.html b/src/main/webapp/views/errorWrkMast/errorWrkMast.html
index 2d5507b..6b2e31d 100644
--- a/src/main/webapp/views/errorWrkMast/errorWrkMast.html
+++ b/src/main/webapp/views/errorWrkMast/errorWrkMast.html
@@ -106,8 +106,10 @@
 
 <script type="text/html" id="operate">
     <a class="layui-btn layui-btn-sm btn-detlShow" lay-event="detlShow">鏄庣粏</a>
+    {{#if (d.wrkSts != 4 && d.wrkSts != 5 && d.wrkSts != 14 && d.wrkSts != 15 && d.wrkSts != 20) { }}
     <a class="layui-btn layui-btn-danger layui-btn-sm btn-complete" lay-event="complete">瀹屾垚</a>
     <a class="layui-btn layui-btn-primary layui-btn-sm btn-cancel" lay-event="cancel">鍙栨秷</a>
+    {{# } }}
 </script>
 
 <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
diff --git a/src/main/webapp/views/wrkMast/wrkMast.html b/src/main/webapp/views/wrkMast/wrkMast.html
index 77b804b..0e6b5ec 100644
--- a/src/main/webapp/views/wrkMast/wrkMast.html
+++ b/src/main/webapp/views/wrkMast/wrkMast.html
@@ -120,8 +120,10 @@
     <a class="layui-btn layui-btn-danger layui-btn-xs btn-error" lay-event="takeNone">绌烘搷浣�</a>
     {{# } }}
     <a class="layui-btn layui-btn-xs btn-detlShow" lay-event="detlShow">鏄庣粏</a>
+    {{#if (d.wrkSts != 4 && d.wrkSts != 5 && d.wrkSts != 14 && d.wrkSts != 15 && d.wrkSts != 20) { }}
     <a class="layui-btn layui-btn-danger layui-btn-xs btn-complete" lay-event="complete">瀹屾垚</a>
     <a class="layui-btn layui-btn-primary layui-btn-xs btn-cancel" lay-event="cancel">鍙栨秷</a>
+    {{# } }}
     {{#if (d.ioType === 103) { }}
         <a class="layui-btn layui-btn-warm layui-btn-xs btn-pick" lay-event="pick">鎷�</a>
     {{# } }}

--
Gitblit v1.9.1