Просмотр исходного кода

订单加密查询,运费模板热加载

yuhongqi 3 недель назад
Родитель
Сommit
d50bb128b8
22 измененных файлов с 497 добавлено и 155 удалено
  1. 2 1
      fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java
  2. 4 3
      fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java
  3. 27 0
      fs-common/src/main/java/com/fs/common/utils/PhoneUtils.java
  4. 2 1
      fs-company/src/main/java/com/fs/company/controller/live/LiveOrderController.java
  5. 4 3
      fs-company/src/main/java/com/fs/store/controller/FsStoreOrderController.java
  6. 3 0
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  7. 3 0
      fs-service-system/src/main/java/com/fs/live/vo/LiveOrderQueryVO.java
  8. 38 0
      fs-service-system/src/main/java/com/fs/store/config/ShippingTemplateRedisConfig.java
  9. 32 0
      fs-service-system/src/main/java/com/fs/store/listener/ShippingTemplateRefreshListener.java
  10. 16 4
      fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderItemMapper.java
  11. 56 14
      fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderMapper.java
  12. 6 0
      fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderParam.java
  13. 77 0
      fs-service-system/src/main/java/com/fs/store/service/ShippingTemplateRefreshService.java
  14. 31 3
      fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesFreeServiceImpl.java
  15. 31 3
      fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesRegionServiceImpl.java
  16. 8 45
      fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesServiceImpl.java
  17. 3 0
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderItemServiceImpl.java
  18. 9 0
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java
  19. 88 75
      fs-service-system/src/main/java/com/fs/store/strategy/ShippingTemplateManager.java
  20. 43 0
      fs-service-system/src/main/java/com/fs/store/util/OrderPhoneSearchHelper.java
  21. 6 1
      fs-service-system/src/main/resources/mapper/live/LiveOrderMapper.xml
  22. 8 2
      fs-service-system/src/main/resources/mapper/store/FsStoreOrderMapper.xml

+ 2 - 1
fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java

@@ -8,6 +8,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
@@ -331,7 +332,7 @@ public class LiveOrderController extends BaseController
     public R getPhone(@PathVariable("id") Long id)
     {
         LiveOrder order = liveOrderService.selectLiveOrderByOrderId(String.valueOf(id));
-        String userPhone = order.getUserPhone();
+        String userPhone = PhoneUtils.resolvePhoneForView(order.getUserPhone());
         return R.ok().put("userPhone",userPhone);
     }
 

+ 4 - 3
fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java

@@ -8,6 +8,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.param.CompanyStoreOrderMoneyLogsListParam;
@@ -307,11 +308,11 @@ public class FsStoreOrderController extends BaseController {
     @GetMapping(value = "/{id}")
     public R getInfo(@PathVariable("id") Long id) {
         FsStoreOrder order = fsStoreOrderService.selectFsStoreOrderById(id);
-        order.setUserPhone(ParseUtils.parsePhone(order.getUserPhone()));
+        order.setUserPhone(PhoneUtils.normalizePhoneForDisplay(order.getUserPhone()));
         order.setUserAddress(ParseUtils.parseAddress(order.getUserAddress()));
         FsUser user = userService.selectFsUserById(order.getUserId());
         if (user!=null){
-            user.setPhone(ParseUtils.parsePhone(user.getPhone()));
+            user.setPhone(PhoneUtils.normalizePhoneForDisplay(user.getPhone()));
         }
 
         FsStoreOrderItem itemMap = new FsStoreOrderItem();
@@ -365,7 +366,7 @@ public class FsStoreOrderController extends BaseController {
     public R getPhone(@PathVariable("id") Long id)
     {
         FsStoreOrder order = fsStoreOrderService.selectFsStoreOrderById(id);
-        String userPhone = order.getUserPhone();
+        String userPhone = PhoneUtils.resolvePhoneForView(order.getUserPhone());
         return R.ok().put("userPhone",userPhone);
     }
 

+ 27 - 0
fs-common/src/main/java/com/fs/common/utils/PhoneUtils.java

@@ -155,6 +155,33 @@ public class PhoneUtils {
         return phone;
     }
 
+    /**
+     * 11位明文搜索时生成密文,供 SQL 同时匹配明文与加密存储
+     */
+    public static String encryptPlainPhoneForSearch(String phone) {
+        if (!isPlainMobile11(phone)) {
+            return null;
+        }
+        return encryptPlainOrKeep(phone);
+    }
+
+    /**
+     * 点击查看完整手机号:11位明文直返,超长密文解密后返回
+     */
+    public static String resolvePhoneForView(String phone) {
+        if (StrUtil.isBlank(phone)) {
+            return phone;
+        }
+        if (isPlainMobile11(phone)) {
+            return phone;
+        }
+        if (isMaskedPhone(phone)) {
+            return phone;
+        }
+        String plain = tryDecryptToPlain(phone);
+        return StrUtil.isNotBlank(plain) ? plain : phone;
+    }
+
     /**
      * 无权限查看时:先解为明文再脱敏展示
      */

+ 2 - 1
fs-company/src/main/java/com/fs/company/controller/live/LiveOrderController.java

@@ -8,6 +8,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
@@ -154,7 +155,7 @@ public class LiveOrderController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         if (loginUser.getUser().getUserType().equals("00")){
             LiveOrder order = liveOrderService.selectLiveOrderByOrderId(String.valueOf(id));
-            String userPhone = order.getUserPhone();
+            String userPhone = PhoneUtils.resolvePhoneForView(order.getUserPhone());
             return R.ok().put("userPhone",userPhone);
         }
         return R.error("无权查看");

+ 4 - 3
fs-company/src/main/java/com/fs/store/controller/FsStoreOrderController.java

@@ -10,6 +10,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
@@ -189,10 +190,10 @@ public class FsStoreOrderController extends BaseController
     public R getInfo(@PathVariable("id") Long id)
     {
         FsStoreOrder order=fsStoreOrderService.selectFsStoreOrderById(id);
-        order.setUserPhone(ParseUtils.parsePhone(order.getUserPhone()));
+        order.setUserPhone(PhoneUtils.normalizePhoneForDisplay(order.getUserPhone()));
         order.setUserAddress(ParseUtils.parseAddress(order.getUserAddress()));
         FsUser user=userService.selectFsUserById(order.getUserId());
-        user.setPhone(ParseUtils.parsePhone(user.getPhone()));
+        user.setPhone(PhoneUtils.normalizePhoneForDisplay(user.getPhone()));
         FsStoreOrderItem itemMap=new FsStoreOrderItem();
         itemMap.setOrderId(order.getId());
         List<FsStoreOrderItem> items=orderItemService.selectFsStoreOrderItemList(itemMap);
@@ -225,7 +226,7 @@ public class FsStoreOrderController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         if (loginUser.getUser().getUserType().equals("00")){
             FsStoreOrder order = fsStoreOrderService.selectFsStoreOrderById(id);
-            String userPhone = order.getUserPhone();
+            String userPhone = PhoneUtils.resolvePhoneForView(order.getUserPhone());
             return R.ok().put("userPhone",userPhone);
         }
         return R.error("无权查看");

+ 3 - 0
fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -79,6 +79,7 @@ import com.fs.store.service.*;
 import com.fs.store.service.channel.PaymentHandler;
 import com.fs.store.service.channel.PaymentHandlerHolder;
 import com.fs.store.service.channel.param.PayProcessContext;
+import com.fs.store.util.OrderPhoneSearchHelper;
 import com.fs.store.vo.FsStoreProductActivityListVO;
 import com.fs.system.config.SnowflakeUtils;
 import com.fs.system.service.ISysConfigService;
@@ -983,6 +984,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Override
     public List<LiveOrder> selectLiveOrderList(LiveOrderQueryVO liveOrder) {
         normalizeLiveOrderQueryPayRange(liveOrder);
+        OrderPhoneSearchHelper.prepare(liveOrder);
         List<LiveOrder> liveOrders = baseMapper.selectLiveOrderList(liveOrder);
         if (CollectionUtils.isEmpty(liveOrders)) {
             return liveOrders;
@@ -1019,6 +1021,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Override
     public List<LiveOrder> selectLiveOrderListExport(LiveOrderQueryVO liveOrder) {
         normalizeLiveOrderQueryPayRange(liveOrder);
+        OrderPhoneSearchHelper.prepare(liveOrder);
         List<LiveOrder> liveOrders = baseMapper.selectLiveOrderList(liveOrder);
         if (CollectionUtils.isEmpty(liveOrders)) {
             return liveOrders;

+ 3 - 0
fs-service-system/src/main/java/com/fs/live/vo/LiveOrderQueryVO.java

@@ -68,6 +68,9 @@ public class LiveOrderQueryVO extends BaseEntity {
     @Excel(name = "收货人电话")
     private String userPhone;
 
+    /** 搜索用收货手机号密文 */
+    private String userPhoneEncrypted;
+
 
     /** 详细地址 */
     @Excel(name = "详细地址")

+ 38 - 0
fs-service-system/src/main/java/com/fs/store/config/ShippingTemplateRedisConfig.java

@@ -0,0 +1,38 @@
+package com.fs.store.config;
+
+import com.fs.store.listener.ShippingTemplateRefreshListener;
+import com.fs.store.service.ShippingTemplateRefreshService;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.listener.ChannelTopic;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+
+/**
+ * 注册运费模板 Redis Pub/Sub 监听;若应用未定义 ListenerContainer 则自动创建
+ */
+@Configuration
+@ConditionalOnClass(RedisMessageListenerContainer.class)
+public class ShippingTemplateRedisConfig {
+
+    @Bean
+    @ConditionalOnMissingBean(RedisMessageListenerContainer.class)
+    public RedisMessageListenerContainer shippingTemplateRedisMessageListenerContainer(
+            RedisConnectionFactory redisConnectionFactory) {
+        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+        container.setConnectionFactory(redisConnectionFactory);
+        return container;
+    }
+
+    @Bean
+    public Object shippingTemplateRefreshListenerRegistration(
+            RedisMessageListenerContainer redisMessageListenerContainer,
+            ShippingTemplateRefreshListener shippingTemplateRefreshListener) {
+        redisMessageListenerContainer.addMessageListener(
+                shippingTemplateRefreshListener,
+                new ChannelTopic(ShippingTemplateRefreshService.CHANNEL));
+        return new Object();
+    }
+}

+ 32 - 0
fs-service-system/src/main/java/com/fs/store/listener/ShippingTemplateRefreshListener.java

@@ -0,0 +1,32 @@
+package com.fs.store.listener;
+
+import com.fs.store.service.ShippingTemplateRefreshService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.connection.MessageListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * 订阅运费模板变更广播,同步失效各实例本地内存
+ */
+@Slf4j
+@Component
+public class ShippingTemplateRefreshListener implements MessageListener {
+
+    @Autowired
+    private ShippingTemplateRefreshService shippingTemplateRefreshService;
+
+    @Override
+    public void onMessage(Message message, byte[] pattern) {
+        if (message == null || message.getBody() == null) {
+            return;
+        }
+        try {
+            Long templateId = Long.valueOf(new String(message.getBody()));
+            shippingTemplateRefreshService.invalidateLocal(templateId);
+        } catch (NumberFormatException e) {
+            log.warn("运费模板变更广播消息格式错误: {}", new String(message.getBody()));
+        }
+    }
+}

+ 16 - 4
fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderItemMapper.java

@@ -92,10 +92,16 @@ public interface FsStoreOrderItemMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -164,13 +170,19 @@ public interface FsStoreOrderItemMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.realName != null and  maps.realName !=\"\"     '> " +
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +

+ 56 - 14
fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderMapper.java

@@ -120,10 +120,16 @@ public interface FsStoreOrderMapper
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -232,10 +238,16 @@ public interface FsStoreOrderMapper
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -342,10 +354,16 @@ public interface FsStoreOrderMapper
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -622,10 +640,16 @@ public interface FsStoreOrderMapper
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -727,10 +751,16 @@ public interface FsStoreOrderMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -820,10 +850,16 @@ public interface FsStoreOrderMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -879,10 +915,16 @@ public interface FsStoreOrderMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +

+ 6 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderParam.java

@@ -15,8 +15,14 @@ public class FsStoreOrderParam extends BaseEntity implements Serializable
 
     private String phone;
 
+    /** 搜索用手机号密文(11位明文自动加密,匹配库中加密存储) */
+    private String phoneEncrypted;
+
     private String userPhone;
 
+    /** 搜索用收货手机号密文 */
+    private String userPhoneEncrypted;
+
     private Integer status;
 
     private Long companyId;

+ 77 - 0
fs-service-system/src/main/java/com/fs/store/service/ShippingTemplateRefreshService.java

@@ -0,0 +1,77 @@
+package com.fs.store.service;
+
+import com.fs.store.strategy.ShippingTemplateManager;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.Set;
+
+/**
+ * 运费模板变更后统一刷新:Redis 计算缓存、本地内存、多实例广播
+ */
+@Slf4j
+@Service
+public class ShippingTemplateRefreshService {
+
+    public static final String CHANNEL = "shipping:template:changed";
+
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Autowired
+    private ShippingTemplateManager shippingTemplateManager;
+
+    public void refresh(Long templateId) {
+        if (templateId == null) {
+            return;
+        }
+        clearShippingTemplateCache(templateId);
+        shippingTemplateManager.invalidate(templateId);
+        publish(templateId);
+        log.info("运费模板已刷新 templateId={}", templateId);
+    }
+
+    public void remove(Long templateId) {
+        if (templateId == null) {
+            return;
+        }
+        clearShippingTemplateCache(templateId);
+        shippingTemplateManager.remove(templateId);
+        publish(templateId);
+        log.info("运费模板已删除缓存 templateId={}", templateId);
+    }
+
+    public void invalidateLocal(Long templateId) {
+        if (templateId == null) {
+            return;
+        }
+        shippingTemplateManager.invalidate(templateId);
+        log.info("收到运费模板变更广播,已失效本地缓存 templateId={}", templateId);
+    }
+
+    private void publish(Long templateId) {
+        try {
+            stringRedisTemplate.convertAndSend(CHANNEL, templateId.toString());
+        } catch (Exception e) {
+            log.error("广播运费模板变更失败 templateId={}", templateId, e);
+        }
+    }
+
+    /**
+     * 清理直播/下单运费 Redis 缓存,key:shipping:template:{templateId}:city:*
+     */
+    public void clearShippingTemplateCache(Long templateId) {
+        try {
+            String cacheKeyPattern = String.format("shipping:template:%s:city:*", templateId);
+            Set<String> keys = stringRedisTemplate.keys(cacheKeyPattern);
+            if (keys != null && !keys.isEmpty()) {
+                stringRedisTemplate.delete(keys);
+                log.info("清理运费模板 Redis 缓存成功 templateId={}, count={}", templateId, keys.size());
+            }
+        } catch (Exception e) {
+            log.error("清理运费模板 Redis 缓存失败 templateId={}", templateId, e);
+        }
+    }
+}

+ 31 - 3
fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesFreeServiceImpl.java

@@ -6,10 +6,12 @@ import java.util.List;
 import com.fs.store.dto.TemplateDTO;
 import com.fs.store.strategy.FreeShippingRule;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import com.fs.store.mapper.FsShippingTemplatesFreeMapper;
 import com.fs.store.domain.FsShippingTemplatesFree;
 import com.fs.store.service.IFsShippingTemplatesFreeService;
+import com.fs.store.service.ShippingTemplateRefreshService;
 
 /**
  * 免邮费Service业务层处理
@@ -23,6 +25,10 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Autowired
     private FsShippingTemplatesFreeMapper fsShippingTemplatesFreeMapper;
 
+    @Autowired
+    @Lazy
+    private ShippingTemplateRefreshService shippingTemplateRefreshService;
+
     /**
      * 查询免邮费
      *
@@ -56,7 +62,9 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Override
     public int insertFsShippingTemplatesFree(FsShippingTemplatesFree fsShippingTemplatesFree)
     {
-        return fsShippingTemplatesFreeMapper.insertFsShippingTemplatesFree(fsShippingTemplatesFree);
+        int result = fsShippingTemplatesFreeMapper.insertFsShippingTemplatesFree(fsShippingTemplatesFree);
+        shippingTemplateRefreshService.refresh(fsShippingTemplatesFree.getTempId());
+        return result;
     }
 
     /**
@@ -68,7 +76,9 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Override
     public int updateFsShippingTemplatesFree(FsShippingTemplatesFree fsShippingTemplatesFree)
     {
-        return fsShippingTemplatesFreeMapper.updateFsShippingTemplatesFree(fsShippingTemplatesFree);
+        int result = fsShippingTemplatesFreeMapper.updateFsShippingTemplatesFree(fsShippingTemplatesFree);
+        shippingTemplateRefreshService.refresh(fsShippingTemplatesFree.getTempId());
+        return result;
     }
 
     /**
@@ -80,6 +90,7 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Override
     public int deleteFsShippingTemplatesFreeByIds(Long[] ids)
     {
+        refreshByFreeIds(ids);
         return fsShippingTemplatesFreeMapper.deleteFsShippingTemplatesFreeByIds(ids);
     }
 
@@ -92,7 +103,24 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Override
     public int deleteFsShippingTemplatesFreeById(Long id)
     {
-        return fsShippingTemplatesFreeMapper.deleteFsShippingTemplatesFreeById(id);
+        FsShippingTemplatesFree free = fsShippingTemplatesFreeMapper.selectFsShippingTemplatesFreeById(id);
+        int result = fsShippingTemplatesFreeMapper.deleteFsShippingTemplatesFreeById(id);
+        if (free != null) {
+            shippingTemplateRefreshService.refresh(free.getTempId());
+        }
+        return result;
+    }
+
+    private void refreshByFreeIds(Long[] ids) {
+        if (ids == null) {
+            return;
+        }
+        for (Long id : ids) {
+            FsShippingTemplatesFree free = fsShippingTemplatesFreeMapper.selectFsShippingTemplatesFreeById(id);
+            if (free != null) {
+                shippingTemplateRefreshService.refresh(free.getTempId());
+            }
+        }
     }
 
     @Override

+ 31 - 3
fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesRegionServiceImpl.java

@@ -3,10 +3,12 @@ package com.fs.store.service.impl;
 import java.util.Collections;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import com.fs.store.mapper.FsShippingTemplatesRegionMapper;
 import com.fs.store.domain.FsShippingTemplatesRegion;
 import com.fs.store.service.IFsShippingTemplatesRegionService;
+import com.fs.store.service.ShippingTemplateRefreshService;
 
 /**
  * 邮费区域Service业务层处理
@@ -20,6 +22,10 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Autowired
     private FsShippingTemplatesRegionMapper fsShippingTemplatesRegionMapper;
 
+    @Autowired
+    @Lazy
+    private ShippingTemplateRefreshService shippingTemplateRefreshService;
+
     /**
      * 查询邮费区域
      *
@@ -53,7 +59,9 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Override
     public int insertFsShippingTemplatesRegion(FsShippingTemplatesRegion fsShippingTemplatesRegion)
     {
-        return fsShippingTemplatesRegionMapper.insertFsShippingTemplatesRegion(fsShippingTemplatesRegion);
+        int result = fsShippingTemplatesRegionMapper.insertFsShippingTemplatesRegion(fsShippingTemplatesRegion);
+        shippingTemplateRefreshService.refresh(fsShippingTemplatesRegion.getTempId());
+        return result;
     }
 
     /**
@@ -65,7 +73,9 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Override
     public int updateFsShippingTemplatesRegion(FsShippingTemplatesRegion fsShippingTemplatesRegion)
     {
-        return fsShippingTemplatesRegionMapper.updateFsShippingTemplatesRegion(fsShippingTemplatesRegion);
+        int result = fsShippingTemplatesRegionMapper.updateFsShippingTemplatesRegion(fsShippingTemplatesRegion);
+        shippingTemplateRefreshService.refresh(fsShippingTemplatesRegion.getTempId());
+        return result;
     }
 
     /**
@@ -77,6 +87,7 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Override
     public int deleteFsShippingTemplatesRegionByIds(Long[] ids)
     {
+        refreshByRegionIds(ids);
         return fsShippingTemplatesRegionMapper.deleteFsShippingTemplatesRegionByIds(ids);
     }
 
@@ -89,7 +100,24 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Override
     public int deleteFsShippingTemplatesRegionById(Long id)
     {
-        return fsShippingTemplatesRegionMapper.deleteFsShippingTemplatesRegionById(id);
+        FsShippingTemplatesRegion region = fsShippingTemplatesRegionMapper.selectFsShippingTemplatesRegionById(id);
+        int result = fsShippingTemplatesRegionMapper.deleteFsShippingTemplatesRegionById(id);
+        if (region != null) {
+            shippingTemplateRefreshService.refresh(region.getTempId());
+        }
+        return result;
+    }
+
+    private void refreshByRegionIds(Long[] ids) {
+        if (ids == null) {
+            return;
+        }
+        for (Long id : ids) {
+            FsShippingTemplatesRegion region = fsShippingTemplatesRegionMapper.selectFsShippingTemplatesRegionById(id);
+            if (region != null) {
+                shippingTemplateRefreshService.refresh(region.getTempId());
+            }
+        }
     }
 
     @Override

+ 8 - 45
fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesServiceImpl.java

@@ -2,7 +2,6 @@ package com.fs.store.service.impl;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
 import cn.hutool.core.bean.BeanUtil;
@@ -19,9 +18,10 @@ import com.fs.store.dto.RegionInfoDTO;
 import com.fs.store.mapper.FsShippingTemplatesFreeMapper;
 import com.fs.store.mapper.FsShippingTemplatesRegionMapper;
 import com.fs.store.param.FsShippingTemplatesAddEditParam;
+import com.fs.store.service.ShippingTemplateRefreshService;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import com.fs.store.mapper.FsShippingTemplatesMapper;
 import com.fs.store.domain.FsShippingTemplates;
@@ -29,7 +29,6 @@ import com.fs.store.service.IFsShippingTemplatesService;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import lombok.extern.slf4j.Slf4j;
-import java.util.Set;
 
 /**
  * 运费模板Service业务层处理
@@ -51,9 +50,8 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
     private FsShippingTemplatesRegionMapper fsShippingTemplatesRegionMapper;
 
     @Autowired
-    private StringRedisTemplate stringRedisTemplate;
-
-
+    @Lazy
+    private ShippingTemplateRefreshService shippingTemplateRefreshService;
 
     /**
      * 查询运费模板
@@ -102,12 +100,7 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
     public int updateFsShippingTemplates(FsShippingTemplates fsShippingTemplates)
     {
         fsShippingTemplates.setUpdateTime(DateUtils.getNowDate());
-        int result = fsShippingTemplatesMapper.updateFsShippingTemplates(fsShippingTemplates);
-        // 清理相关缓存
-        if (fsShippingTemplates.getId() != null) {
-            clearShippingTemplateCache(fsShippingTemplates.getId());
-        }
-        return result;
+        return fsShippingTemplatesMapper.updateFsShippingTemplates(fsShippingTemplates);
     }
 
     /**
@@ -120,10 +113,9 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
     public int deleteFsShippingTemplatesByIds(Long[] ids)
     {
         int result = fsShippingTemplatesMapper.deleteFsShippingTemplatesByIds(ids);
-        // 清理相关缓存
         if (ids != null && ids.length > 0) {
             for (Long id : ids) {
-                clearShippingTemplateCache(id);
+                shippingTemplateRefreshService.remove(id);
             }
         }
         return result;
@@ -139,9 +131,8 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
     public int deleteFsShippingTemplatesById(Long ids)
     {
         int result = fsShippingTemplatesMapper.deleteFsShippingTemplatesById(ids);
-        // 清理相关缓存
         if (ids != null) {
-            clearShippingTemplateCache(ids);
+            shippingTemplateRefreshService.remove(ids);
         }
         return result;
     }
@@ -158,7 +149,6 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
         shippingTemplates.setAppointInfo(JSON.toJSONString(fsShippingTemplates.getAppointInfo()));
         if(fsShippingTemplates.getId() != null && fsShippingTemplates.getId()  > 0){
             shippingTemplates.setId(fsShippingTemplates.getId());
-            // updateFsShippingTemplates 方法内部已经会清理缓存
             this.updateFsShippingTemplates(shippingTemplates);
         }else{
             shippingTemplates.setCreateTime(DateUtils.getNowDate());
@@ -167,6 +157,7 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
 
         this.saveRegion(fsShippingTemplates,shippingTemplates.getId());
         this.saveFreeReigion(fsShippingTemplates,shippingTemplates.getId());
+        shippingTemplateRefreshService.refresh(shippingTemplates.getId());
         return R.ok();
     }
 
@@ -191,7 +182,6 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
         List<FsShippingTemplatesRegion> fsShippingTemplatesRegions = new ArrayList<>();
 
         for (RegionInfoDTO regionInfoDto : regionInfo){
-            String uni = IdUtil.simpleUUID();
             if(regionInfoDto.getRegion() != null && !regionInfoDto.getRegion().isEmpty()){
                 for (RegionDTO regionDto : regionInfoDto.getRegion()){
                     if(regionDto.getChildren() != null && !regionDto.getChildren().isEmpty()){
@@ -265,31 +255,4 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
             fsShippingTemplatesFreeMapper.saveBatch(shippingTemplatesFreeList);
         }
     }
-
-    /**
-     * 清理运费模板相关的缓存
-     * 缓存key格式:shipping:template:{templateId}:city:{cityIds}
-     * 
-     * @param templateId 运费模板ID
-     */
-    private void clearShippingTemplateCache(Long templateId) {
-        try {
-            if (templateId == null) {
-                return;
-            }
-            // 构建缓存key前缀:shipping:template:{templateId}:city:*
-            String cacheKeyPattern = String.format("shipping:template:%s:city:*", templateId);
-            // 查找所有匹配的缓存key
-            Set<String> keys = stringRedisTemplate.keys(cacheKeyPattern);
-            if (keys != null && !keys.isEmpty()) {
-                // 批量删除匹配的缓存
-                stringRedisTemplate.delete(keys);
-                log.info("清理运费模板缓存成功,templateId: {}, 删除缓存数量: {}", templateId, keys.size());
-            } else {
-                log.debug("未找到需要清理的运费模板缓存,templateId: {}", templateId);
-            }
-        } catch (Exception e) {
-            log.error("清理运费模板缓存失败,templateId: {}", templateId, e);
-        }
-    }
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderItemServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.store.service.impl;
 
 import java.util.List;
 
+import com.fs.store.util.OrderPhoneSearchHelper;
 import com.fs.store.param.FsStoreOrderParam;
 import com.fs.store.vo.FsStoreOrderItemExportVO;
 import com.fs.store.vo.FsStoreOrderItemVO;
@@ -102,11 +103,13 @@ public class FsStoreOrderItemServiceImpl implements IFsStoreOrderItemService
 
     @Override
     public List<FsStoreOrderItemExportVO> selectFsStoreOrderItemListExportVO(FsStoreOrderParam fsStoreOrder) {
+        OrderPhoneSearchHelper.prepare(fsStoreOrder);
         return fsStoreOrderItemMapper.selectFsStoreOrderItemListExportVO(fsStoreOrder);
     }
 
     @Override
     public Long countFsStoreOrderItemListExportVO(FsStoreOrderParam fsStoreOrder) {
+        OrderPhoneSearchHelper.prepare(fsStoreOrder);
         return fsStoreOrderItemMapper.itemsCount(fsStoreOrder);
     }
 

+ 9 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java

@@ -92,6 +92,7 @@ import com.fs.store.service.channel.PaymentHandlerHolder;
 import com.fs.store.service.channel.param.PayProcessContext;
 import com.fs.store.strategy.ShippingOrder;
 import com.fs.store.strategy.ShippingTemplateManager;
+import com.fs.store.util.OrderPhoneSearchHelper;
 import com.fs.store.vo.*;
 import com.fs.system.config.SnowflakeUtils;
 import com.fs.system.service.ISysConfigService;
@@ -565,6 +566,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderVO> selectFsStoreOrderListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsStoreOrderListVO(param);
         for(FsStoreOrderVO vo:list){
             String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
@@ -582,6 +584,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderVO> selectFsStoreOrderAllListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsStoreOrderAllListVO(param);
         for(FsStoreOrderVO vo:list){
             String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
@@ -599,6 +602,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderVO> selectPayRemainListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsPayRemainListVO(param);
         for(FsStoreOrderVO vo:list){
             String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
@@ -618,6 +622,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsPromotionOrderVO> selectFsPromotionOrderListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsPromotionOrderVO> list = fsStoreOrderMapper.selectFsPromotionOrderListVO(param);
         for(FsPromotionOrderVO vo:list){
             String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
@@ -2883,6 +2888,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderExportVO> selectFsStoreOrderListVOByExport(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderExportVO> fsStoreOrderExportVOS = fsStoreOrderMapper.selectFsStoreOrderListVOByExport(param);
         Map<Long, FsStorePayment> paymentMap = fsStorePaymentMapper.selectAllPayments();
         for (FsStoreOrderExportVO item : fsStoreOrderExportVOS) {
@@ -2896,6 +2902,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderPromotionExportVO> selectFsPromotionOrderListVOByExport(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderPromotionExportVO> list = fsStoreOrderMapper.selectFsPromotionOrderListVOByExport(param);
         for (FsStoreOrderPromotionExportVO vo : list){
            FsStoreOrderBrokerageVO brokerageVO = fsStoreOrderMapper.selectBrokerage(vo.getId());
@@ -2908,6 +2915,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStorePayRemainOrderExportVO> selectFsStorePayRemainOrderListVOByExport(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         return fsStoreOrderMapper.selectFsStorePayRemainOrderListVOByExport(param);
     }
 
@@ -2918,6 +2926,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderVO> selectFsCustomerStoreOrderListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         return fsStoreOrderMapper.selectFsCustomerStoreOrderListVO(param);
     }
 

+ 88 - 75
fs-service-system/src/main/java/com/fs/store/strategy/ShippingTemplateManager.java

@@ -8,121 +8,134 @@ import com.fs.store.enums.ShippingTempEnum;
 import com.fs.store.service.IFsShippingTemplatesFreeService;
 import com.fs.store.service.IFsShippingTemplatesRegionService;
 import com.fs.store.service.IFsShippingTemplatesService;
-import com.fs.store.strategy.impl.CountBasedStrategy;
-import com.fs.store.strategy.impl.WeightBasedStrategy;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.ObjectUtils;
 import org.apache.http.util.Asserts;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
-import javax.annotation.PostConstruct;
 import java.math.BigDecimal;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * 运费模板管理器
+ * 运费模板管理器(懒加载,变更后 invalidate 即可热更新)
  */
 @Slf4j
 @Service
 public class ShippingTemplateManager {
     @Autowired
+    @Lazy
     private IFsShippingTemplatesService fsShippingTemplatesService;
     @Autowired
+    @Lazy
     private IFsShippingTemplatesRegionService fsShippingTemplatesRegionService;
     @Autowired
+    @Lazy
     private IFsShippingTemplatesFreeService fsShippingTemplatesFreeService;
 
     private final Map<Long, ShippingTemplate> TEMPLATES = new ConcurrentHashMap<>();
 
     private static final Map<Integer, String> TEMPLATE_TYPE_MAP = new ConcurrentHashMap<>();
     static {
-        TEMPLATE_TYPE_MAP.put(1,"count");
-        TEMPLATE_TYPE_MAP.put(2,"weight");
-        TEMPLATE_TYPE_MAP.put(3,"volume");
+        TEMPLATE_TYPE_MAP.put(1, "count");
+        TEMPLATE_TYPE_MAP.put(2, "weight");
+        TEMPLATE_TYPE_MAP.put(3, "volume");
     }
 
-    @PostConstruct
-    public void init(){
-        log.info("正在初始化运费模板管理器...");
-        // 查询运费模板
-        List<FsShippingTemplates> fsShippingTemplates = fsShippingTemplatesService.listAllTemplate();
-        for (FsShippingTemplates template : fsShippingTemplates) {
-            String type = TEMPLATE_TYPE_MAP.get(template.getType());
-            Asserts.notNull(type,"不支持的模板类型");
-
-            ShippingTemplate shippingTemplate = new ShippingTemplate(template.getId(),type);
-
-            log.info("正在加载模板配送区域及运费");
-            List<FsShippingTemplatesRegion> fsShippingTemplatesRegions = fsShippingTemplatesRegionService.selectTempRegionByTempIdAndCityId(template.getId());
-            for (FsShippingTemplatesRegion templatesRegion : fsShippingTemplatesRegions) {
-                Region region = new Region();
-                region.setCityId(templatesRegion.getCityId());
-                // 如果是按重量
-                if(ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_2.getValue())){
-                    region.setFirstWeight(templatesRegion.getFirst());
-                    region.setFirstWeightFee(templatesRegion.getFirstPrice());
-                    region.setAdditionalWeight(templatesRegion.getContinues());
-                    region.setAdditionalWeightFee(templatesRegion.getContinuePrice());
-                } else if(ObjectUtil.equal(templatesRegion.getType(),ShippingTempEnum.TYPE_1.getValue())){
-                    region.setFirstItem(templatesRegion.getFirst());
-                    region.setFirstItemFee(templatesRegion.getFirstPrice());
-                    region.setAdditionalItemFee(templatesRegion.getContinuePrice());
-                } else if(ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_3.getValue())){
-                    region.setFirstVolume(templatesRegion.getFirst());
-                    region.setFirstVolumeFee(templatesRegion.getFirstPrice());
-                    region.setAdditionalVolume(templatesRegion.getContinues());
-                    region.setAdditionalVolumeFee(templatesRegion.getContinuePrice());
-                }
-                shippingTemplate.addRegion(region);
-            }
-
-
-            log.info("模板加载区域完成: {}个", fsShippingTemplatesRegions.size());
-
-            log.info("正在加载模板包邮规则");
-            List<FsShippingTemplatesFree> freeShippingRules = fsShippingTemplatesFreeService.selectFreeShippingRuleByTempId(template.getId());
-            for (FsShippingTemplatesFree freeShippingRule : freeShippingRules) {
-                FreeShippingRule rule = new FreeShippingRule();
-                rule.setRegion(freeShippingRule.getCityId());
-
-                if(ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_2.getValue())){
-                    rule.setMinWeight(freeShippingRule.getNumber());
-                    rule.setMinAmount(freeShippingRule.getPrice());
-                } else if(ObjectUtil.equal(freeShippingRule.getType(),ShippingTempEnum.TYPE_1.getValue())){
-                    rule.setMinCount(freeShippingRule.getNumber());
-                    rule.setMinAmount(freeShippingRule.getPrice());
-                } else if(ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_3.getValue())){
-                    rule.setMinVolume(freeShippingRule.getNumber());
-                    rule.setMinAmount(freeShippingRule.getPrice());
-                }
-
-                shippingTemplate.addFreeShippingRule(rule);
-            }
-            log.info("模板包邮规则加载完成: {} 个", freeShippingRules);
-
-            this.addTemplate(shippingTemplate);
+    public void invalidate(Long templateId) {
+        if (templateId != null) {
+            TEMPLATES.remove(templateId);
         }
-        log.info("运费模板管理器初始化完成: {}个", fsShippingTemplates.size());
     }
 
-    public void addTemplate(ShippingTemplate template) {
-        TEMPLATES.put(template.getId(), template);
+    public void remove(Long templateId) {
+        invalidate(templateId);
+    }
+
+    public void reload(Long templateId) {
+        invalidate(templateId);
+        getTemplate(templateId);
     }
 
     public ShippingTemplate getTemplate(Long templateId) {
-        return TEMPLATES.get(templateId);
+        if (templateId == null) {
+            return null;
+        }
+        ShippingTemplate cached = TEMPLATES.get(templateId);
+        if (cached != null) {
+            return cached;
+        }
+        ShippingTemplate loaded = buildTemplateFromDb(templateId);
+        if (loaded != null) {
+            TEMPLATES.put(templateId, loaded);
+        }
+        return loaded;
     }
 
     public BigDecimal calculateShippingFee(Long templateId, ShippingOrder order) {
-        ShippingTemplate template = TEMPLATES.get(templateId);
+        ShippingTemplate template = getTemplate(templateId);
         if (template == null) {
             throw new IllegalArgumentException("找不到运费模板: " + templateId);
         }
         return template.calculateShippingFee(order);
     }
-}
 
+    private ShippingTemplate buildTemplateFromDb(Long templateId) {
+        FsShippingTemplates template = fsShippingTemplatesService.selectFsShippingTemplatesById(templateId);
+        if (template == null || ObjectUtil.equal(template.getIsDel(), 1)) {
+            log.warn("运费模板不存在或已删除 templateId={}", templateId);
+            return null;
+        }
+        String type = TEMPLATE_TYPE_MAP.get(template.getType());
+        Asserts.notNull(type, "不支持的模板类型");
+
+        ShippingTemplate shippingTemplate = new ShippingTemplate(template.getId(), type);
+
+        List<FsShippingTemplatesRegion> regions =
+                fsShippingTemplatesRegionService.selectTempRegionByTempIdAndCityId(template.getId());
+        for (FsShippingTemplatesRegion templatesRegion : regions) {
+            Region region = new Region();
+            region.setCityId(templatesRegion.getCityId());
+            if (ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_2.getValue())) {
+                region.setFirstWeight(templatesRegion.getFirst());
+                region.setFirstWeightFee(templatesRegion.getFirstPrice());
+                region.setAdditionalWeight(templatesRegion.getContinues());
+                region.setAdditionalWeightFee(templatesRegion.getContinuePrice());
+            } else if (ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_1.getValue())) {
+                region.setFirstItem(templatesRegion.getFirst());
+                region.setFirstItemFee(templatesRegion.getFirstPrice());
+                region.setAdditionalItemFee(templatesRegion.getContinuePrice());
+            } else if (ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_3.getValue())) {
+                region.setFirstVolume(templatesRegion.getFirst());
+                region.setFirstVolumeFee(templatesRegion.getFirstPrice());
+                region.setAdditionalVolume(templatesRegion.getContinues());
+                region.setAdditionalVolumeFee(templatesRegion.getContinuePrice());
+            }
+            shippingTemplate.addRegion(region);
+        }
+
+        List<FsShippingTemplatesFree> freeShippingRules =
+                fsShippingTemplatesFreeService.selectFreeShippingRuleByTempId(template.getId());
+        for (FsShippingTemplatesFree freeShippingRule : freeShippingRules) {
+            FreeShippingRule rule = new FreeShippingRule();
+            rule.setRegion(freeShippingRule.getCityId());
+            if (ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_2.getValue())) {
+                rule.setMinWeight(freeShippingRule.getNumber());
+                rule.setMinAmount(freeShippingRule.getPrice());
+            } else if (ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_1.getValue())) {
+                rule.setMinCount(freeShippingRule.getNumber());
+                rule.setMinAmount(freeShippingRule.getPrice());
+            } else if (ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_3.getValue())) {
+                rule.setMinVolume(freeShippingRule.getNumber());
+                rule.setMinAmount(freeShippingRule.getPrice());
+            }
+            shippingTemplate.addFreeShippingRule(rule);
+        }
+
+        log.debug("懒加载运费模板 templateId={}, regions={}, freeRules={}",
+                templateId, regions.size(), freeShippingRules.size());
+        return shippingTemplate;
+    }
+}

+ 43 - 0
fs-service-system/src/main/java/com/fs/store/util/OrderPhoneSearchHelper.java

@@ -0,0 +1,43 @@
+package com.fs.store.util;
+
+import cn.hutool.core.util.StrUtil;
+import com.fs.common.utils.PhoneUtils;
+import com.fs.live.vo.LiveOrderQueryVO;
+import com.fs.store.param.FsStoreOrderParam;
+
+/**
+ * 订单手机号搜索:11位明文同时匹配库中明文与密文
+ */
+public final class OrderPhoneSearchHelper {
+
+    private OrderPhoneSearchHelper() {
+    }
+
+    public static void prepare(FsStoreOrderParam param) {
+        if (param == null) {
+            return;
+        }
+        if (StrUtil.isNotBlank(param.getUserPhone())) {
+            String encrypted = PhoneUtils.encryptPlainPhoneForSearch(param.getUserPhone());
+            if (StrUtil.isNotBlank(encrypted)) {
+                param.setUserPhoneEncrypted(encrypted);
+            }
+        }
+        if (StrUtil.isNotBlank(param.getPhone())) {
+            String encrypted = PhoneUtils.encryptPlainPhoneForSearch(param.getPhone());
+            if (StrUtil.isNotBlank(encrypted)) {
+                param.setPhoneEncrypted(encrypted);
+            }
+        }
+    }
+
+    public static void prepare(LiveOrderQueryVO param) {
+        if (param == null || StrUtil.isBlank(param.getUserPhone())) {
+            return;
+        }
+        String encrypted = PhoneUtils.encryptPlainPhoneForSearch(param.getUserPhone());
+        if (StrUtil.isNotBlank(encrypted)) {
+            param.setUserPhoneEncrypted(encrypted);
+        }
+    }
+}

+ 6 - 1
fs-service-system/src/main/resources/mapper/live/LiveOrderMapper.xml

@@ -130,7 +130,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="appCompanyUserId != null"> and fu.app_company_user_id = #{appCompanyUserId}</if>
             <if test="appCompanyUserName != null and appCompanyUserName != ''"> and fu.app_company_user_name like concat('%', #{appCompanyUserName}, '%')</if>
             <if test="userName != null  and userName != ''"> and a.user_name like concat('%', #{userName}, '%')</if>
-            <if test="userPhone != null  and userPhone != ''"> and a.user_phone = #{userPhone}</if>
+            <if test="userPhone != null  and userPhone != ''">
+                and (a.user_phone like concat(#{userPhone},'%')
+                <if test="userPhoneEncrypted != null and userPhoneEncrypted != ''">
+                    or a.user_phone like concat(#{userPhoneEncrypted},'%')
+                </if>)
+            </if>
             <if test="userAddress != null  and userAddress != ''"> and a.user_address = #{userAddress}</if>
             <if test="cartId != null  and cartId != ''"> and cart_id = #{cartId}</if>
             <if test="totalNum != null  and totalNum != ''"> and total_num = #{totalNum}</if>

+ 8 - 2
fs-service-system/src/main/resources/mapper/store/FsStoreOrderMapper.xml

@@ -610,10 +610,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 and o.real_name like CONCAT(#{maps.realName},'%')
             </if>
             <if test = 'maps.phone != null and  maps.phone !=""     '>
-                and u.phone like CONCAT(#{maps.phone},'%')
+                and (u.phone like CONCAT(#{maps.phone},'%')
+                <if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted != ""'>
+                    or u.phone like CONCAT(#{maps.phoneEncrypted},'%')
+                </if>)
             </if>
             <if test = 'maps.userPhone != null and  maps.userPhone !=""     '>
-                and o.user_phone like CONCAT(#{maps.userPhone},'%')
+                and (o.user_phone like CONCAT(#{maps.userPhone},'%')
+                <if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted != ""'>
+                    or o.user_phone like CONCAT(#{maps.userPhoneEncrypted},'%')
+                </if>)
             </if>
             <if test = 'maps.status != null    '>
                 and o.status =#{maps.status}