uw = new UpdateWrapper<>();
- uw.eq("order_id", orderId).in("status", 1, 2)
+ uw.eq("order_id", orderId)
.set("status", 0)
.set("order_id", null)
.set("use_time", null);
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/UserPendingOrderCacheUtil.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/UserPendingOrderCacheUtil.java
new file mode 100644
index 00000000..9abf521f
--- /dev/null
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/UserPendingOrderCacheUtil.java
@@ -0,0 +1,273 @@
+package cc.hiver.mall.utils;
+
+import cc.hiver.core.common.redis.RedisTemplateHelper;
+import cc.hiver.mall.pojo.vo.MallOrderVO;
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鐢ㄦ埛寰呭畬鎴愯鍗曠紦瀛樺伐鍏风被
+ *
+ * 搴曞眰浣跨敤 Redis Hash 缁撴瀯锛屼繚璇佹寜 userId + orderId 缁村害鐨 O(1) 璇诲啓鏁堢巼銆
+ *
+ * Key = USER_PENDING_ORDERS:{userId}
+ * Field = orderId
+ * Value = MallOrderVO 鐨 JSON 搴忓垪鍖
+ *
+ *
+ * 浣跨敤鍦烘櫙锛氳鍗曠姸鎬佸彂鐢熷彉鍖栨椂锛堝垱寤恒佹洿鏂般佸彇娑堛佸畬鎴愮瓑锛夛紝
+ * 鐢变笟鍔℃柟涓诲姩璋冪敤鏈伐鍏风被鐨勬柟娉曠淮鎶ょ紦瀛橈紝浠ュ噺灏 getOrdersByUserId 鎺ュ彛瀵规暟鎹簱鐨勬煡璇㈠帇鍔涖
+ *
+ * @author system
+ */
+@Slf4j
+@Component
+public class UserPendingOrderCacheUtil {
+
+ /** Redis Key 鍓嶇紑 */
+ private static final String KEY_PREFIX = "USER_PENDING_ORDERS:";
+
+ /** 璁㈠崟瀹屾垚/鍙栨秷/閫娆剧瓑涓嶅啀灞炰簬"寰呭畬鎴"鐨勭姸鎬侀泦鍚 */
+ private static final int STATUS_DONE = 5;
+ private static final int STATUS_CANCELLED = 6;
+ private static final int STATUS_REFUNDED = 8;
+ private static final int STATUS_RETURNED = 12;
+
+ @Autowired
+ private RedisTemplateHelper redisTemplateHelper;
+
+ // ================================================================
+ // Key 鏋勫缓
+ // ================================================================
+
+ private String buildKey(String userId) {
+ return KEY_PREFIX + userId;
+ }
+
+ // ================================================================
+ // 瀛樻斁锛坧ut锛
+ // ================================================================
+
+ /**
+ * 瀛樻斁鍗曚釜璁㈠崟鍒扮紦瀛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @param orderVO 璁㈠崟VO锛堝繀椤诲寘鍚湁鏁堢殑 id锛
+ */
+ public void put(String userId, MallOrderVO orderVO) {
+ if (StringUtils.isBlank(userId) || orderVO == null || StringUtils.isBlank(orderVO.getId())) {
+ log.warn("UserPendingOrderCacheUtil.put 鍙傛暟鏃犳晥, userId={}, orderVO={}", userId, orderVO);
+ return;
+ }
+ try {
+ String key = buildKey(userId);
+ String json = JSONUtil.toJsonStr(orderVO);
+ redisTemplateHelper.hPut(key, orderVO.getId(), json);
+ log.debug("缂撳瓨鐢ㄦ埛寰呭畬鎴愯鍗: userId={}, orderId={}", userId, orderVO.getId());
+ } catch (Exception e) {
+ log.error("缂撳瓨鐢ㄦ埛寰呭畬鎴愯鍗曞け璐: userId={}, orderId={}", userId, orderVO.getId(), e);
+ }
+ }
+
+ /**
+ * 鎵归噺瀛樻斁璁㈠崟鍒扮紦瀛橈紙閫氬父鐢ㄤ簬缂撳瓨棰勭儹 / 棣栨鍔犺浇锛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @param orders 璁㈠崟鍒楄〃
+ */
+ public void putAll(String userId, List orders) {
+ if (StringUtils.isBlank(userId) || orders == null || orders.isEmpty()) {
+ return;
+ }
+ try {
+ String key = buildKey(userId);
+ java.util.Map map = new java.util.LinkedHashMap<>(orders.size());
+ for (MallOrderVO order : orders) {
+ if (order != null && StringUtils.isNotBlank(order.getId())) {
+ map.put(order.getId(), JSONUtil.toJsonStr(order));
+ }
+ }
+ if (!map.isEmpty()) {
+ redisTemplateHelper.hPutAll(key, map);
+ log.debug("鎵归噺缂撳瓨鐢ㄦ埛寰呭畬鎴愯鍗: userId={}, count={}", userId, map.size());
+ }
+ } catch (Exception e) {
+ log.error("鎵归噺缂撳瓨鐢ㄦ埛寰呭畬鎴愯鍗曞け璐: userId={}", userId, e);
+ }
+ }
+
+ // ================================================================
+ // 鍒犻櫎锛坮emove锛
+ // ================================================================
+
+ /**
+ * 鏍规嵁 userId 鍜 orderId 浠庣紦瀛樹腑鍒犻櫎鎸囧畾璁㈠崟
+ *
+ * 鍏稿瀷鍦烘櫙锛氳鍗曞畬鎴愩佸彇娑堛侀娆炬垚鍔熷悗璋冪敤銆
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @param orderId 璁㈠崟ID
+ */
+ public void remove(String userId, String orderId) {
+ if (StringUtils.isBlank(userId) || StringUtils.isBlank(orderId)) {
+ log.warn("UserPendingOrderCacheUtil.remove 鍙傛暟鏃犳晥, userId={}, orderId={}", userId, orderId);
+ return;
+ }
+ try {
+ String key = buildKey(userId);
+ redisTemplateHelper.hDelete(key, orderId);
+ log.debug("鍒犻櫎鐢ㄦ埛寰呭畬鎴愯鍗曠紦瀛: userId={}, orderId={}", userId, orderId);
+ } catch (Exception e) {
+ log.error("鍒犻櫎鐢ㄦ埛寰呭畬鎴愯鍗曠紦瀛樺け璐: userId={}, orderId={}", userId, orderId, e);
+ }
+ }
+
+ /**
+ * 娓呴櫎鎸囧畾鐢ㄦ埛鐨勬墍鏈夊緟瀹屾垚璁㈠崟缂撳瓨
+ *
+ * 鍏稿瀷鍦烘櫙锛氶渶瑕佸己鍒跺埛鏂拌鐢ㄦ埛缂撳瓨鏃惰皟鐢ㄣ
+ *
+ * @param userId 鐢ㄦ埛ID
+ */
+ public void removeAll(String userId) {
+ if (StringUtils.isBlank(userId)) {
+ return;
+ }
+ try {
+ redisTemplateHelper.delete(buildKey(userId));
+ log.debug("娓呴櫎鐢ㄦ埛鍏ㄩ儴寰呭畬鎴愯鍗曠紦瀛: userId={}", userId);
+ } catch (Exception e) {
+ log.error("娓呴櫎鐢ㄦ埛鍏ㄩ儴寰呭畬鎴愯鍗曠紦瀛樺け璐: userId={}", userId, e);
+ }
+ }
+
+ // ================================================================
+ // 鏇存柊锛坲pdate锛
+ // ================================================================
+
+ /**
+ * 鏍规嵁 userId 鍜 orderId 鏇存柊缂撳瓨涓殑璁㈠崟淇℃伅
+ *
+ * 濡傛灉鏇存柊鍚庣殑璁㈠崟鐘舵佸凡缁忎笉灞炰簬"寰呭畬鎴"锛坰tatus 鈭 {5,6,8,12}锛夛紝
+ * 鍒欒嚜鍔ㄤ粠缂撳瓨涓Щ闄よ璁㈠崟锛屾棤闇璋冪敤鏂归澶栧垽鏂
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @param orderVO 鏇存柊鍚庣殑璁㈠崟VO
+ */
+ public void update(String userId, MallOrderVO orderVO) {
+ if (StringUtils.isBlank(userId) || orderVO == null || StringUtils.isBlank(orderVO.getId())) {
+ log.warn("UserPendingOrderCacheUtil.update 鍙傛暟鏃犳晥, userId={}, orderVO={}", userId, orderVO);
+ return;
+ }
+ try {
+ // 濡傛灉璁㈠崟鐘舵佸凡涓嶅睘浜庡緟瀹屾垚锛岀洿鎺ュ垹闄
+ if (isTerminalStatus(orderVO.getStatus())) {
+ remove(userId, orderVO.getId());
+ log.debug("璁㈠崟宸茬粓鎬侊紝浠庣紦瀛樼Щ闄: userId={}, orderId={}, status={}",
+ userId, orderVO.getId(), orderVO.getStatus());
+ return;
+ }
+ // 鍚﹀垯瑕嗙洊鏇存柊
+ put(userId, orderVO);
+ log.debug("鏇存柊鐢ㄦ埛寰呭畬鎴愯鍗曠紦瀛: userId={}, orderId={}, status={}",
+ userId, orderVO.getId(), orderVO.getStatus());
+ } catch (Exception e) {
+ log.error("鏇存柊鐢ㄦ埛寰呭畬鎴愯鍗曠紦瀛樺け璐: userId={}, orderId={}", userId, orderVO.getId(), e);
+ }
+ }
+
+ // ================================================================
+ // 鏌ヨ锛坓et锛
+ // ================================================================
+
+ /**
+ * 鑾峰彇鐢ㄦ埛鍏ㄩ儴寰呭畬鎴愯鍗曠紦瀛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缂撳瓨鐨勮鍗曞垪琛紝缂撳瓨涓嶅瓨鍦ㄦ椂杩斿洖 null锛堣皟鐢ㄦ柟鍙嵁姝ゅ垽鏂槸鍚﹂渶瑕佸洖婧愭煡搴擄級
+ */
+ public List getAll(String userId) {
+ if (StringUtils.isBlank(userId)) {
+ return null;
+ }
+ try {
+ String key = buildKey(userId);
+ Map