Ver Fonte

批处理打卡广场详情。

dujian há 1 dia atrás
pai
commit
3432b650af

+ 127 - 129
alien-store/src/main/java/shop/alien/store/service/LifeUserStoreService.java

@@ -53,6 +53,12 @@ public class LifeUserStoreService {
 
     private final StoreBusinessInfoMapper storeBusinessInfoMapper;
 
+    private static final List<String> BUSINESS_SECTION_STORE_TYPE_NEW_1 =
+            Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
+    private static final List<String> BUSINESS_SECTION_STORE_TYPE_NEW_2 =
+            Arrays.asList("丽人美发", "运动健身");
+    private static final String BUSINESS_SECTION_STORE_TYPE_NEW_3 = "特色美食";
+
     /**
      * 门店列表
      *
@@ -67,8 +73,6 @@ public class LifeUserStoreService {
      */
     public List<Map<String, Object>> getStoreList(String storeType, String storeName, Integer distance, String jingdu, String weidu, int page, int size) {
         try {
-            // 初始化返回结果列表
-            List<Map<String, Object>> returnMaps = new ArrayList<>();
             // 构建查询条件对象
             QueryWrapper<StoreInfoVo> wrapper = new QueryWrapper<>();
             // 添加门店类型筛选条件()
@@ -90,7 +94,7 @@ public class LifeUserStoreService {
             List<StoreInfoVo> storeInfoVoList = storeInfoMapper.getStoreInfoVoListNew(wrapper,jingdu + "," + weidu);
             // 如果查询结果为空,则直接返回空列表
             if (storeInfoVoList.isEmpty()) {
-                return returnMaps;
+                return new ArrayList<>();
             }
             // 提取所有符合条件的门店ID
             List<Integer> storeIds = storeInfoVoList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
@@ -112,133 +116,104 @@ public class LifeUserStoreService {
             List<Map<Integer, Integer>> storeClockInCountList = storeClockInService.getStoreClockInCount();
             // 获取所有店铺打卡次数(有图片并且设置为可见的)
             List<Map<Integer, Integer>> storeClockInCountMapList = storeClockInService.getStoreClockInWithCanLookCount();
-            // 遍历所有门店信息,构造返回结果
-            for (StoreInfoVo store : storeInfoVoList) {
-
-                //门店营业时间信息 Fixme 流式处理,或用 <assiociate>一次性查询
-                StoreBusinessInfo storeBusinessInfo = storeBusinessInfoMapper.selectOne(new QueryWrapper<StoreBusinessInfo>().eq("store_id", store.getId()).eq("delete_flag", 0).last("limit 1"));
-
-                Map<String, Object> storeMap = new HashMap<>();
-                // 如果用户提供了经纬度信息,则计算并添加门店到用户的距离
-                /*if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
-                    double storeJing = Double.parseDouble(store.getStorePosition().split(",")[0]);
-                    double storeWei = Double.parseDouble(store.getStorePosition().split(",")[1]);
-                    double storeDistance = DistanceUtil.haversineCalculateDistance(Double.parseDouble(jingdu), Double.parseDouble(weidu), storeJing, storeWei);
-                    storeMap.put("distance", storeDistance);
-                } else {
-                    // 否则,返回提示信息
-                    storeMap.put("distance", "没有位置信息");
-                }*/
-                storeMap.put("distance", store.getDist());
-                // 添加门店的业务状态及其描述
-                storeMap.put("businessStatus", store.getBusinessStatus());
-                storeMap.put("businessStatusStr", store.getBusinessStatusStr());
-
-                String businessSectionName = store.getBusinessSectionName();
-                if(Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗").contains(businessSectionName)){
-                    storeMap.put("storeTypeNew", 1);
-                } else if (Arrays.asList("丽人美发", "运动健身").contains(businessSectionName)){
-                    storeMap.put("storeTypeNew", 2);
-                } else if (Arrays.asList("特色美食").contains(businessSectionName)){
-                    storeMap.put("storeTypeNew", 3);
-                }
-                //474bug
-                storeMap.put("businessSection", store.getBusinessSection());
-                storeMap.put("businessSectionName", store.getBusinessSectionName());
-                storeMap.put("businessTypes", store.getBusinessTypes());
-                storeMap.put("businessTypesName", store.getBusinessTypesName());
-                storeMap.put("businessClassify", store.getBusinessClassify());
-                storeMap.put("businessClassifyName", store.getBusinessClassifyName());
-                storeMap.put("storeBusinessInfo", storeBusinessInfo);
-                // 添加门店ID
-                storeMap.put("storeId", store.getId());
-                // 如果存在评分数据,则添加评分、平均消费及评价总数
-                if (avgScoreMap.containsKey(String.valueOf(store.getId()))) {
-                    storeMap.put("avgScore", avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score"));
-                    //storeMap.put("avgPrice", avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price"));
-                    // 条数
-                    storeMap.put("totalNum", avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num"));
-                } else {
-                    // 否则,设置默认值
-                    storeMap.put("avgScore", 0);
-                    //storeMap.put("avgPrice", 0);
-                    storeMap.put("totalNum", 0);
-                }
-                if (avgPriceMap.containsKey(String.valueOf(store.getId()))) {
-                    //storeMap.put("avgScore", avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score"));
-                    storeMap.put("avgPrice", avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price"));
-                    // 条数
-                    //storeMap.put("totalNum", avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num"));
-                } else {
-                    // 否则,设置默认值
-                    //storeMap.put("avgScore", 0);
-                    storeMap.put("avgPrice", 0);
-                    //storeMap.put("totalNum", 0);
-                }
-                // 添加门店名称
-                storeMap.put("storeName", store.getStoreName());
-                // 添加门店地址
-                storeMap.put("storeAddress", store.getStoreAddress());
-                // 添加门店类型
-                storeMap.put("storeType", store.getStoreType());
-                // 添加门店入口图片
-                storeMap.put("entranceImage", store.getEntranceImage());
-                // 添加门店图片
-                storeMap.put("storeImage", store.getImgUrl());
-                // 添加门店简介
-                storeMap.put("storeBlurb",store.getStoreBlurb());
-                // 解析并添加门店经纬度
-                String[] position = store.getStorePosition().split(",");
-                storeMap.put("longitude", position.length == 2 ? position[0] : "");
-                storeMap.put("latitude", position.length == 2 ? position[1] : "");
-                // 构造该门店的优惠券列表
-                List<Map<String, Object>> quanMapList = new ArrayList<>();
-                if (!quanList.isEmpty()) {
-                    for (LifeCoupon quan : quanList) {
-                        // 如果优惠券的门店ID与当前门店ID匹配,则添加到优惠券列表中
-                        if (store.getId().toString().equals(quan.getStoreId())) {
-                            Map<String, Object> quanMap = new HashMap<>();
-                            quanMap.put("quanType", quan.getType());
-                            quanMap.put("name", quan.getName());
-                            quanMap.put("price", quan.getPrice());
-                            // 折扣价
-                            quanMap.put("offprice", quan.getOffprice());
-                            quanMap.put("quanId", quan.getId());
-                            quanMapList.add(quanMap);
-                        }
-                    }
-                    // 将优惠券列表添加到门店信息中
-                    storeMap.put("quanList", quanMapList);
-                }
-                // 添加门店类型的描述
-                storeMap.put("storeTypeStr", store.getStoreTypeStr());
-                // 遍历打卡次数列表,找到当前门店的打卡次数并添加到门店信息中
-                storeClockInCountList.forEach(b -> {
-                    Integer storeId = b.get("storeId");
-                    if (Objects.equals(storeId, store.getId())) {
-                        storeMap.put("storeClockInCount", b.get("count"));
-                    }
-                });
-
-                storeClockInCountMapList.forEach(b -> {
-                    Integer storeId = b.get("storeId");
-                    if (Objects.equals(storeId, store.getId())) {
-                        storeMap.put("storeClockInCountWithCanLook", b.get("count"));
-                    }
-                });
-
-                // 如果未找到打卡次数,则设置为0
-                if (null == storeMap.get("storeClockInCount")) {
-                    storeMap.put("storeClockInCount", 0);
-                }
-                // 如果未找到打卡次数(有图片并且设置为可见的),则设置为0
-                if (null == storeMap.get("storeClockInCountWithCanLook")) {
-                    storeMap.put("storeClockInCountWithCanLook", 0);
-                    continue;
-                }
-                // 将当前门店的信息添加到返回结果列表中
-                returnMaps.add(storeMap);
+
+            // 一次查出本页门店的营业时间,避免循环内 N+1 查询
+            List<StoreBusinessInfo> businessInfoRows = storeBusinessInfoMapper.selectList(
+                    new LambdaQueryWrapper<StoreBusinessInfo>()
+                            .in(StoreBusinessInfo::getStoreId, storeIds)
+                            .eq(StoreBusinessInfo::getDeleteFlag, 0));
+            Map<Integer, StoreBusinessInfo> businessInfoByStoreId = new HashMap<>();
+            for (StoreBusinessInfo row : businessInfoRows) {
+                businessInfoByStoreId.putIfAbsent(row.getStoreId(), row);
             }
+
+            Map<String, List<LifeCoupon>> quanByStoreId = quanList.stream()
+                    .filter(q -> q.getStoreId() != null)
+                    .collect(Collectors.groupingBy(LifeCoupon::getStoreId));
+
+            Map<Integer, Integer> clockInCountByStoreId = buildStoreIdToCountMap(storeClockInCountList);
+            Map<Integer, Integer> clockInCanLookCountByStoreId = buildStoreIdToCountMap(storeClockInCountMapList);
+
+            final boolean hasGlobalQuan = !quanList.isEmpty();
+            // 流式组装配,避免对优惠券表、打卡汇总表在每家店上重复全表扫描
+            List<Map<String, Object>> returnMaps = storeInfoVoList.stream()
+                    .map(store -> {
+                        StoreBusinessInfo storeBusinessInfo = businessInfoByStoreId.get(store.getId());
+
+                        Map<String, Object> storeMap = new HashMap<>();
+                        // 如果用户提供了经纬度信息,则计算并添加门店到用户的距离
+                        /*if ((jingdu != null && !jingdu.isEmpty()) && (weidu != null && !weidu.isEmpty())) {
+                            double storeJing = Double.parseDouble(store.getStorePosition().split(",")[0]);
+                            double storeWei = Double.parseDouble(store.getStorePosition().split(",")[1]);
+                            double storeDistance = DistanceUtil.haversineCalculateDistance(Double.parseDouble(jingdu), Double.parseDouble(weidu), storeJing, storeWei);
+                            storeMap.put("distance", storeDistance);
+                        } else {
+                            // 否则,返回提示信息
+                            storeMap.put("distance", "没有位置信息");
+                        }*/
+                        storeMap.put("distance", store.getDist());
+                        storeMap.put("businessStatus", store.getBusinessStatus());
+                        storeMap.put("businessStatusStr", store.getBusinessStatusStr());
+
+                        String businessSectionName = store.getBusinessSectionName();
+                        if (BUSINESS_SECTION_STORE_TYPE_NEW_1.contains(businessSectionName)) {
+                            storeMap.put("storeTypeNew", 1);
+                        } else if (BUSINESS_SECTION_STORE_TYPE_NEW_2.contains(businessSectionName)) {
+                            storeMap.put("storeTypeNew", 2);
+                        } else if (BUSINESS_SECTION_STORE_TYPE_NEW_3.equals(businessSectionName)) {
+                            storeMap.put("storeTypeNew", 3);
+                        }
+                        storeMap.put("businessSection", store.getBusinessSection());
+                        storeMap.put("businessSectionName", store.getBusinessSectionName());
+                        storeMap.put("businessTypes", store.getBusinessTypes());
+                        storeMap.put("businessTypesName", store.getBusinessTypesName());
+                        storeMap.put("businessClassify", store.getBusinessClassify());
+                        storeMap.put("businessClassifyName", store.getBusinessClassifyName());
+                        storeMap.put("storeBusinessInfo", storeBusinessInfo);
+                        storeMap.put("storeId", store.getId());
+                        if (avgScoreMap.containsKey(String.valueOf(store.getId()))) {
+                            storeMap.put("avgScore", avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score"));
+                            storeMap.put("totalNum", avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num"));
+                        } else {
+                            storeMap.put("avgScore", 0);
+                            storeMap.put("totalNum", 0);
+                        }
+                        if (avgPriceMap.containsKey(String.valueOf(store.getId()))) {
+                            storeMap.put("avgPrice", avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price"));
+                        } else {
+                            storeMap.put("avgPrice", 0);
+                        }
+                        storeMap.put("storeName", store.getStoreName());
+                        storeMap.put("storeAddress", store.getStoreAddress());
+                        storeMap.put("storeType", store.getStoreType());
+                        storeMap.put("entranceImage", store.getEntranceImage());
+                        storeMap.put("storeImage", store.getImgUrl());
+                        storeMap.put("storeBlurb", store.getStoreBlurb());
+                        String[] position = store.getStorePosition().split(",");
+                        storeMap.put("longitude", position.length == 2 ? position[0] : "");
+                        storeMap.put("latitude", position.length == 2 ? position[1] : "");
+
+                        if (hasGlobalQuan) {
+                            String sid = String.valueOf(store.getId());
+                            List<LifeCoupon> forStore = quanByStoreId.getOrDefault(sid, Collections.emptyList());
+                            List<Map<String, Object>> quanMapList = forStore.stream().map(quan -> {
+                                Map<String, Object> quanMap = new HashMap<>();
+                                quanMap.put("quanType", quan.getType());
+                                quanMap.put("name", quan.getName());
+                                quanMap.put("price", quan.getPrice());
+                                quanMap.put("offprice", quan.getOffprice());
+                                quanMap.put("quanId", quan.getId());
+                                return quanMap;
+                            }).collect(Collectors.toList());
+                            storeMap.put("quanList", quanMapList);
+                        }
+
+                        storeMap.put("storeTypeStr", store.getStoreTypeStr());
+                        storeMap.put("storeClockInCount", clockInCountByStoreId.getOrDefault(store.getId(), 0));
+                        storeMap.put("storeClockInCountWithCanLook", clockInCanLookCountByStoreId.getOrDefault(store.getId(), 0));
+                        return storeMap;
+                    })
+                    .collect(Collectors.toList());
             // 如果用户提供了距离阈值,则根据距离过滤结果,并按距离升序排序
             if (distance != null) {
                 double maxDistance = distance;
@@ -286,6 +261,29 @@ public class LifeUserStoreService {
             throw new RuntimeException(e);
         }
     }
+
+    /**
+     * MyBatis 将 {@code store_id as storeId} 等别名列进 Map,按行整理为 门店id 到 次数 的映射,供列表 O(1) 查询。
+     */
+    private static Map<Integer, Integer> buildStoreIdToCountMap(List<Map<Integer, Integer>> rows) {
+        Map<Integer, Integer> out = new HashMap<>();
+        if (rows == null) {
+            return out;
+        }
+        for (Object o : rows) {
+            if (!(o instanceof Map)) {
+                continue;
+            }
+            Map<?, ?> row = (Map<?, ?>) o;
+            Object sid = row.get("storeId");
+            Object c = row.get("count");
+            if (sid != null && c != null) {
+                out.put(((Number) sid).intValue(), ((Number) c).intValue());
+            }
+        }
+        return out;
+    }
+
     // 提取一个工具方法,统一处理距离值的转换
     private double getDistanceValue(Object distanceObj) {
         if (distanceObj instanceof Number) {