Răsfoiți Sursa

八大类代码上sit全部

zhangchen 2 săptămâni în urmă
părinte
comite
9e4646662b

+ 221 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartRequest;
@@ -781,4 +782,224 @@ public class StoreInfoController {
         }
         return R.data(ocrData);
     }
+
+    /**
+     * 查询四种类型店铺(酒吧、ktv、洗浴汗蒸、按摩足浴)并按距离筛选
+     *
+     * @param lon         经度
+     * @param lat         纬度
+     * @param distance    距离范围(单位:公里)
+     * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
+     * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧需要查询字典表),可选,如果指定则只查询该类型
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
+     */
+    @ApiOperation("查询四种类型店铺(酒吧、ktv、洗浴汗蒸、按摩足浴)并按距离筛选")
+    @ApiOperationSupport(order = 16)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "distance", value = "距离范围(单位:公里)", dataType = "Double", paramType = "query"),
+            @ApiImplicitParam(name = "sortType", value = "排序模式(1:智能排序,2:好评优先,3:距离优先)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "businessType", value = "店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,丽人美发=6,运动健身=7,酒吧=11)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "categoryId", value = "字典表id,根据此id查询经营板块、经营种类、分类并匹配店铺", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/getSpecialTypeStoresByDistance")
+    public R<IPage<StoreInfoVo>> getSpecialTypeStoresByDistance(
+            @RequestParam("lon") Double lon,
+            @RequestParam("lat") Double lat,
+            @RequestParam(value = "distance", required = false) Double distance,
+            @RequestParam(value = "sortType", required = false, defaultValue = "1") Integer sortType,
+            @RequestParam(value = "businessType", required = false) Integer businessType,
+            @RequestParam(value = "categoryId", required = false) Integer categoryId,
+            @RequestParam(defaultValue = "1") int pageNum,
+            @RequestParam(defaultValue = "10") int pageSize) {
+        log.info("StoreInfoController.getSpecialTypeStoresByDistance?lon={},lat={},distance={},sortType={},businessType={},categoryId={},pageNum={},pageSize={}",
+                lon, lat, distance, sortType, businessType, categoryId, pageNum, pageSize);
+
+        try {
+            // 参数校验:经度范围 [-180, 180],纬度范围 [-90, 90]
+            if (lon == null || lat == null) {
+                return R.fail("经纬度参数不能为空");
+            }
+
+            // 智能检测:如果参数可能传反了(lat超出范围但lon在范围内),给出提示
+            if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
+                return R.fail(String.format("参数可能传反了!当前值: lon=%s, lat=%s。经度范围: [-180, 180],纬度范围: [-90, 90]。请检查参数顺序。", lon, lat));
+            }
+
+            if (lon < -180 || lon > 180) {
+                return R.fail("经度参数超出有效范围 [-180, 180],当前值: " + lon);
+            }
+            if (lat < -90 || lat > 90) {
+                return R.fail("纬度参数超出有效范围 [-90, 90],当前值: " + lat);
+            }
+
+            // 调用服务层获取筛选结果
+            IPage<StoreInfoVo> result = storeInfoService.getSpecialTypeStoresByDistance(lon, lat, distance, sortType, businessType, categoryId, pageNum, pageSize);
+
+            // 记录响应日志
+            log.info("四种类型店铺距离筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}",
+                    result.getTotal(), result.getCurrent(), result.getSize());
+
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            log.warn("四种类型店铺距离筛选参数错误: {}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("四种类型店铺距离筛选异常", e);
+            return R.fail("筛选失败,请稍后重试");
+        }
+    }
+
+
+
+    /**
+     * 获取休闲娱乐分类数据(主分类和子分类)
+     * 根据图片需求,返回层级结构的分类数据
+     *
+     * @return R<List<StoreDictionaryVo>> 分类列表,包含主分类和子分类
+     */
+    @ApiOperation("获取休闲娱乐分类数据(主分类和子分类)")
+    @ApiOperationSupport(order = 18)
+    @GetMapping("/getLeisureEntertainmentCategories")
+    public R<List<StoreDictionaryVo>> getLeisureEntertainmentCategories() {
+        log.info("StoreInfoController.getLeisureEntertainmentCategories");
+        try {
+            List<StoreDictionaryVo> result = storeInfoService.getLeisureEntertainmentCategories();
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取休闲娱乐分类数据异常", e);
+            return R.fail("获取分类数据失败,请稍后重试");
+        }
+    }
+
+    /**
+     * 获取休闲娱乐分类数据(主分类和子分类)
+     * 根据图片需求,返回层级结构的分类数据
+     *getAllBusinessSection
+     * @return R<List<StoreDictionary>> 分类列表,包含主分类和子分类
+     */
+
+
+    @ApiOperation("获取所有经营板块以及子类")
+    @ApiOperationSupport(order = 18)
+    @GetMapping("/getAllBusinessSection")
+    public R<List<StoreDictionary>> queryBusinessSectionTree(
+            @ApiParam(value = "一级分类dictId,可选,如果传入则只返回该一级分类下的二级和三级分类", required = false)
+            @RequestParam(required = false) String businessSection) {
+        log.info("platformBusinessSection.queryBusinessSectionTree, businessSection={}", businessSection);
+
+        try {
+            List<StoreDictionary> result = storeInfoService.getAllBusinessSection(businessSection);
+            return R.data(result);
+        }catch (Exception e){
+            log.error("获取休闲娱乐分类数据异常", e);
+            return R.fail("获取分类数据失败,请稍后重试");
+        }
+
+    }
+
+
+    @ApiOperation(value = "获取banner图详情")
+    @ApiOperationSupport(order = 7)
+    @GetMapping("/getBannerUrlInfo")
+    @ResponseBody
+    public R getBannerUrlInfo(@RequestParam("storeId") String storeId, @RequestParam("businessId") Integer businessId) {
+        log.info("StoreInfoController.getBannerUrlInfo?storeId={},businessId{}", storeId, businessId);
+
+        try {
+
+            return R.data(storeInfoService.getBannerUrlInfo(storeId, businessId));
+
+        } catch (Exception e) {
+
+            log.error("StoreInfoController.getBannerUrlInfo ERROR Msg={}", e.getMessage(), e);
+
+            return R.fail("查询失败");
+        }
+
+    }
+
+
+    /**
+     * 查询两种类型店铺(丽人美发、运动健身)并按距离筛选
+     *
+     * @param lon         经度
+     * @param lat         纬度
+     * @param distance    距离范围(单位:公里)
+     * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
+     * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,丽人美发=6,运动健身=7),可选,如果指定则只查询该类型
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
+     */
+    @ApiOperation("查询四种类型店铺(丽人美发、运动健身)并按距离筛选")
+    @ApiOperationSupport(order = 16)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query", required = true),
+            @ApiImplicitParam(name = "distance", value = "距离范围(单位:公里)", dataType = "Double", paramType = "query"),
+            @ApiImplicitParam(name = "sortType", value = "排序模式(1:智能排序,2:好评优先,3:距离优先)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "businessType", value = "店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,丽人美发=6,运动健身=7,酒吧=11)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "categoryId", value = "字典表id,根据此id查询经营板块、经营种类、分类并匹配店铺", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/getLifeServicesByDistance")
+    public R<IPage<StoreInfoVo>> getLifeServicesByDistance(
+            @RequestParam("lon") Double lon,
+            @RequestParam("lat") Double lat,
+            @RequestParam(value = "distance", required = false) Double distance,
+            @RequestParam(value = "sortType", required = false, defaultValue = "1") Integer sortType,
+            @RequestParam(value = "businessType", required = false) Integer businessType,
+            @RequestParam(value = "categoryId", required = false) Integer categoryId,
+            @RequestParam(defaultValue = "1") int pageNum,
+            @RequestParam(defaultValue = "10") int pageSize) {
+        log.info("StoreInfoController.getLifeServicesByDistance?lon={},lat={},distance={},sortType={},businessType={},categoryId={},pageNum={},pageSize={}",
+                lon, lat, distance, sortType, businessType, categoryId, pageNum, pageSize);
+
+        try {
+            // 参数校验:经度范围 [-180, 180],纬度范围 [-90, 90]
+            if (lon == null || lat == null) {
+                return R.fail("经纬度参数不能为空");
+            }
+
+            // 智能检测:如果参数可能传反了(lat超出范围但lon在范围内),给出提示
+            if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
+                return R.fail(String.format("参数可能传反了!当前值: lon=%s, lat=%s。经度范围: [-180, 180],纬度范围: [-90, 90]。请检查参数顺序。", lon, lat));
+            }
+
+            if (lon < -180 || lon > 180) {
+                return R.fail("经度参数超出有效范围 [-180, 180],当前值: " + lon);
+            }
+            if (lat < -90 || lat > 90) {
+                return R.fail("纬度参数超出有效范围 [-90, 90],当前值: " + lat);
+            }
+
+            // 调用服务层获取筛选结果
+            IPage<StoreInfoVo> result = storeInfoService.getLifeServicesByDistance(lon, lat, distance, sortType, businessType, categoryId, pageNum, pageSize);
+
+            // 记录响应日志
+            log.info("四种类型店铺距离筛选响应 - 总记录数: {}, 当前页: {}, 页大小: {}",
+                    result.getTotal(), result.getCurrent(), result.getSize());
+
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            log.warn("四种类型店铺距离筛选参数错误: {}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("四种类型店铺距离筛选异常", e);
+            return R.fail("筛选失败,请稍后重试");
+        }
+    }
+
+
+
+
+
+
 }

+ 82 - 4
alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java

@@ -4,10 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.multipart.MultipartRequest;
-import shop.alien.entity.store.StoreBusinessInfo;
-import shop.alien.entity.store.StoreImg;
-import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.StoreInfoDraft;
+import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.StoreInfoDto;
 import shop.alien.entity.store.vo.*;
 
@@ -303,4 +300,85 @@ public interface StoreInfoService extends IService<StoreInfo> {
     Map<String, Object> getStoreOcrData(String storeUserId, String imageUrl);
 
     void aiApproveStoreInfo(AiApproveStoreInfo aiApproveStoreInfo);
+
+
+    /**
+     * 查询四种类型店铺(酒吧、ktv、洗浴汗蒸、按摩足浴)并按距离筛选
+     *
+     * @param lon         经度
+     * @param lat         纬度
+     * @param distance    距离范围(单位:公里)
+     * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
+     * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧需要查询字典表),可选
+     * @param categoryId 字典表id,根据此id查询经营板块、经营种类、分类并匹配店铺,可选
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @return IPage<StoreInfoVo> 分页的门店信息列表
+     */
+    IPage<StoreInfoVo> getSpecialTypeStoresByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, int pageNum, int pageSize);
+
+
+
+    /**
+     * 获取休闲娱乐分类数据(主分类和子分类)
+     * 返回层级结构的分类数据,包含主分类和对应的子分类
+     *
+     * @return List<StoreDictionaryVo> 分类列表,包含主分类和子分类
+     */
+    List<StoreDictionaryVo> getLeisureEntertainmentCategories();
+
+
+    List<StoreDictionary> getAllBusinessSection();
+
+    /**
+     * 根据一级分类获取该分类下的二级和三级分类
+     *
+     * @param businessSection 一级分类的dictId(可选,如果为空则返回所有分类)
+     * @return List<StoreDictionary> 分类树形结构
+     */
+    List<StoreDictionary> getAllBusinessSection(String businessSection);
+
+
+    /**
+     * 你可能还喜欢(推荐店铺)
+     * 根据一级分类、二级分类、三级分类进行店铺筛选
+     * 筛选顺序:先三级,然后二级,最后一级
+     *
+     * @param businessSection 一级分类(经营板块)
+     * @param businessTypes 二级分类(经营种类)
+     * @param businessClassify 三级分类(分类)
+     * @param lon 经度
+     * @param lat 纬度
+     * @return List<StoreInfoVo> 店铺信息列表
+     */
+    List<StoreInfoVo> getRecommendedStores(String businessSection, String businessTypes, String businessClassify, Double lon, Double lat);
+
+
+
+
+
+    /**
+     * 查询两种类型店铺(丽人美发、运动健身)并按距离筛选
+     *
+     * @param lon         经度
+     * @param lat         纬度
+     * @param distance    距离范围(单位:公里)
+     * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
+     * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,丽人美发=6,运动健身=7),可选,如果指定则只查询该类型
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
+     */
+    IPage<StoreInfoVo> getLifeServicesByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, int pageNum, int pageSize);
+
+    /**
+     * 获取活动banner图
+     */
+    List<StoreImg> getBannerUrl (String storeId);
+    /**
+     * 获取活动详情banner图
+     */
+
+    List<StoreImg> getBannerUrlInfo(String storeId, Integer businessId);
+
 }

+ 1294 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java

@@ -2673,4 +2673,1298 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
         }
         return map;
     }
+
+    /**
+     * 获取活动banner图
+     */
+
+    public List<StoreImg> getBannerUrl(String storeId){
+        LambdaQueryWrapper<StoreImg> queryWrapper = new LambdaQueryWrapper<StoreImg>()
+                .eq(StoreImg::getStoreId, Integer.parseInt(storeId))
+                .eq(StoreImg::getImgType, 26)
+                .eq(StoreImg::getDeleteFlag, 0);
+        return storeImgMapper.selectList(queryWrapper);
+    }
+
+
+
+    /**
+     * 获取活动详情banner图
+     */
+
+    public List<StoreImg> getBannerUrlInfo(String storeId, Integer businessId){
+        LambdaQueryWrapper<StoreImg> queryWrapper = new LambdaQueryWrapper<StoreImg>()
+                .eq(StoreImg::getStoreId, Integer.parseInt(storeId))
+                .eq(StoreImg::getImgType, 27)
+                .eq(StoreImg::getDeleteFlag, 0)
+                .eq(StoreImg::getBusinessId, businessId);
+        return storeImgMapper.selectList(queryWrapper);
+    }
+
+
+
+
+    @Override
+    public IPage<StoreInfoVo> getLifeServicesByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, int pageNum, int pageSize) {
+        // 参数校验
+        if (lon == null || lat == null) {
+            throw new IllegalArgumentException("经纬度参数不能为空");
+        }
+
+        // 智能检测:如果参数可能传反了(lat超出范围但lon在范围内),给出提示
+        if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
+            throw new IllegalArgumentException(
+                    String.format("参数可能传反了!当前值: lon=%s, lat=%s。经度范围: [-180, 180],纬度范围: [-90, 90]。请检查参数顺序。", lon, lat)
+            );
+        }
+
+        // 校验经纬度范围:经度 [-180, 180],纬度 [-90, 90]
+        if (lon < -180 || lon > 180) {
+            throw new IllegalArgumentException("经度参数超出有效范围 [-180, 180],当前值: " + lon);
+        }
+        if (lat < -90 || lat > 90) {
+            throw new IllegalArgumentException("纬度参数超出有效范围 [-90, 90],当前值: " + lat);
+        }
+        final int finalSortType = (sortType == null || sortType < 1 || sortType > 3) ? 1 : sortType; // 默认智能排序
+        if (pageNum <= 0) {
+            pageNum = 1;
+        }
+        if (pageSize <= 0) {
+            pageSize = 10;
+        }
+
+        // 构建查询条件
+        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
+
+        // 如果传入了dictId,根据字典id查询经营板块、经营种类、分类并匹配店铺
+        if (categoryId != null) {
+            // 根据categoryId查询字典表记录
+            StoreDictionary dict = storeDictionaryMapper.selectById(categoryId);
+            if (dict == null || dict.getDeleteFlag() == 1) {
+                throw new IllegalArgumentException("字典id不存在或已删除: " + categoryId);
+            }
+
+            String typeName = dict.getTypeName();
+            String dictIdStr =dict.getDictId();
+
+            if ("business_section".equals(typeName)) {
+                // 如果是经营板块,直接匹配business_section
+                try {
+                    Integer sectionId = Integer.parseInt(dictIdStr);
+                    queryWrapper.eq("a.business_section", sectionId);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException("经营板块dictId格式错误: " + dictIdStr);
+                }
+            } else if ("business_type".equals(typeName)) {
+                // 如果是经营种类,需要:
+                // 1. 向上查找父级(经营板块)
+                // 2. 匹配business_section和business_types
+                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
+                if (parentDict == null || !"business_section".equals(parentDict.getTypeName())) {
+                    throw new IllegalArgumentException("经营种类的父级不是经营板块,categoryId: " + categoryId);
+                }
+
+                try {
+                    Integer sectionId = Integer.parseInt(parentDict.getDictId());
+                    queryWrapper.eq("a.business_section", sectionId);
+                    // 使用FIND_IN_SET匹配business_types字段(逗号分隔)
+                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", dictIdStr);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException("经营板块或经营种类dictId格式错误");
+                }
+            } else if ("business_classify".equals(typeName)) {
+                // 如果是分类,需要:
+                // 1. 向上查找父级(经营种类)
+                // 2. 向上查找祖父级(经营板块)
+                // 3. 匹配business_section、business_types和business_classify
+                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
+                if (parentDict == null || !"business_type".equals(parentDict.getTypeName())) {
+                    throw new IllegalArgumentException("分类的父级不是经营种类,categoryId: " + categoryId);
+                }
+
+                StoreDictionary grandParentDict = storeDictionaryMapper.selectById(parentDict.getParentId());
+                if (grandParentDict == null || !"business_section".equals(grandParentDict.getTypeName())) {
+                    throw new IllegalArgumentException("经营种类的父级不是经营板块,categoryId: " + categoryId);
+                }
+
+                try {
+                    Integer sectionId = Integer.parseInt(grandParentDict.getDictId());
+                    queryWrapper.eq("a.business_section", sectionId);
+                    // 使用FIND_IN_SET匹配business_types字段
+                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", parentDict.getDictId());
+                    // 使用FIND_IN_SET匹配business_classify字段
+                    queryWrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", dictIdStr);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException("经营板块、经营种类或分类dictId格式错误");
+                }
+            } else {
+                throw new IllegalArgumentException("不支持的字典类型: " + typeName + ", categoryId: " + categoryId);
+            }
+        } else if (businessType != null) {
+            // 如果指定了businessType,则根据传入的数值进行筛选
+            // 直接使用传入的数值作为business_section进行筛选
+            // KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧的数值未知(由调用方传入)
+            queryWrapper.eq("a.business_section", businessType);
+        } else {
+            // 如果没有指定businessType,则查询所有两种类型的店铺
+            // 需要查询字典表获取所有四种类型的dictId
+            List<String> storeTypeNames = Arrays.asList("丽人美发","运动健身");
+            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
+                    new LambdaQueryWrapper<StoreDictionary>()
+                            .eq(StoreDictionary::getTypeName, "business_section")
+                            .in(StoreDictionary::getDictDetail, storeTypeNames)
+                            .eq(StoreDictionary::getDeleteFlag, 0)
+            );
+
+            List<Integer> businessSectionIds = storeDictionaries.stream()
+                    .filter(d -> StringUtils.isNotEmpty(d.getDictId()))
+                    .map(StoreDictionary::getDictId)
+                    .map(dictIdStr -> {
+                        try {
+                            return Integer.parseInt(dictIdStr);
+                        } catch (NumberFormatException e) {
+                            return null;
+                        }
+                    })
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+
+            // 使用business_section字段进行筛选
+            queryWrapper.in("a.business_section", businessSectionIds);
+        }
+
+        // 过滤已删除的门店
+        queryWrapper.eq("a.delete_flag", 0);
+        // 过滤注销的门店
+        queryWrapper.eq("a.logout_flag", 0);
+        // 过滤禁用的门店
+        queryWrapper.ne("a.store_status", 0);
+        // 过滤永久关门的店铺
+        queryWrapper.ne("a.business_status", 99);
+        // 过滤过期的经营许可证
+        queryWrapper.ge("a.entertainment_licence_expiration_time", new Date());
+
+        // 距离优先模式:只显示10公里内且3.5星以上的店铺
+        final Double finalDistance;
+        if (finalSortType == 3) {
+            queryWrapper.ge("a.score_avg", 3.5);
+            if (distance == null || distance <= 0) {
+                finalDistance = 10.0; // 默认10公里
+            } else if (distance > 10) {
+                finalDistance = 10.0; // 距离优先最多10公里
+            } else {
+                finalDistance = distance;
+            }
+        } else {
+            finalDistance = distance;
+        }
+
+        // 先按距离排序获取所有数据(用于计算距离)
+        queryWrapper.orderByAsc("dist");
+
+        // 创建分页对象(先获取更多数据用于排序计算)
+        IPage<StoreInfoVo> page = new Page<>(1, 1000); // 先获取足够多的数据
+        IPage<StoreInfoVo> storeInfoIPage = storeInfoMapper.getPageForDistance(page, lon + "," + lat, queryWrapper);
+        List<StoreInfoVo> storeInfoVoList = storeInfoIPage.getRecords();
+
+        // 如果指定了距离范围,进行距离筛选
+        if (finalDistance != null && finalDistance > 0) {
+            storeInfoVoList = storeInfoVoList.stream()
+                    .filter(store -> {
+                        String distStr = store.getDist();
+                        if (distStr == null || distStr.isEmpty()) {
+                            return false;
+                        }
+                        try {
+                            double storeDistance = Double.parseDouble(distStr);
+                            return storeDistance <= finalDistance;
+                        } catch (NumberFormatException e) {
+                            return false;
+                        }
+                    })
+                    .collect(Collectors.toList());
+        }
+
+        // 计算时间范围
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime sevenDaysAgo = now.minusDays(7);
+        LocalDateTime thirtyDaysAgo = now.minusDays(30);
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String sevenDaysAgoStr = sevenDaysAgo.format(formatter);
+        String thirtyDaysAgoStr = thirtyDaysAgo.format(formatter);
+
+        // 提取所有门店ID
+        List<Integer> storeIds = storeInfoVoList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
+
+        if (CollectionUtils.isEmpty(storeIds)) {
+            // 如果没有符合条件的店铺,返回空结果
+            IPage<StoreInfoVo> emptyPage = new Page<>(pageNum, pageSize);
+            emptyPage.setRecords(new ArrayList<>());
+            emptyPage.setTotal(0);
+            return emptyPage;
+        }
+
+        // 查询近7天销量(订单数)
+        Map<Integer, Long> sales7DaysMap = new HashMap<>();
+        if (finalSortType == 1) { // 智能排序需要销量数据
+            LambdaQueryWrapper<LifeUserOrder> orderWrapper = new LambdaQueryWrapper<>();
+            orderWrapper.in(LifeUserOrder::getStoreId, storeIds)
+                    .and(w -> w.and(w1 -> w1.eq(LifeUserOrder::getStatus, 7)
+                                    .ge(LifeUserOrder::getFinishTime, sevenDaysAgoStr))
+                            .or(w2 -> w2.eq(LifeUserOrder::getStatus, 1)
+                                    .ge(LifeUserOrder::getPayTime, sevenDaysAgoStr)))
+                    .eq(LifeUserOrder::getDeleteFlag, 0);
+            List<LifeUserOrder> orders7Days = lifeUserOrderMapper.selectList(orderWrapper);
+            Map<Integer, Long> tempSalesMap = orders7Days.stream()
+                    .filter(order -> order.getStoreId() != null)
+                    .collect(Collectors.groupingBy(
+                            order -> Integer.parseInt(order.getStoreId()),
+                            Collectors.counting()));
+            sales7DaysMap.putAll(tempSalesMap);
+        }
+
+        // 查询近30天好评数(score >= 4.5)
+        Map<Integer, Long> goodComment30DaysMap = new HashMap<>();
+        // 查询近7天评论数
+        Map<Integer, Long> comment7DaysMap = new HashMap<>();
+        // 查询总评论数
+        Map<Integer, Long> totalCommentMap = new HashMap<>();
+
+        if (finalSortType == 2) { // 好评优先需要评论数据
+            // 近30天好评数
+            LambdaQueryWrapper<StoreComment> goodCommentWrapper = new LambdaQueryWrapper<>();
+            goodCommentWrapper.in(StoreComment::getStoreId, storeIds)
+                    .eq(StoreComment::getBusinessType, 5)
+                    .eq(StoreComment::getDeleteFlag, 0)
+                    .isNull(StoreComment::getReplyId)
+                    .ge(StoreComment::getScore, 4.5)
+                    .ge(StoreComment::getCreatedTime, thirtyDaysAgoStr);
+            List<StoreComment> goodComments30Days = storeCommentMapper.selectList(goodCommentWrapper);
+            Map<Integer, Long> tempGoodCommentMap = goodComments30Days.stream()
+                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
+            goodComment30DaysMap.putAll(tempGoodCommentMap);
+
+            // 近7天评论数
+            LambdaQueryWrapper<StoreComment> comment7DaysWrapper = new LambdaQueryWrapper<>();
+            comment7DaysWrapper.in(StoreComment::getStoreId, storeIds)
+                    .eq(StoreComment::getBusinessType, 5)
+                    .eq(StoreComment::getDeleteFlag, 0)
+                    .isNull(StoreComment::getReplyId)
+                    .ge(StoreComment::getCreatedTime, sevenDaysAgoStr);
+            List<StoreComment> comments7Days = storeCommentMapper.selectList(comment7DaysWrapper);
+            Map<Integer, Long> tempComment7DaysMap = comments7Days.stream()
+                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
+            comment7DaysMap.putAll(tempComment7DaysMap);
+
+            // 总评论数
+            LambdaQueryWrapper<StoreComment> totalCommentWrapper = new LambdaQueryWrapper<>();
+            totalCommentWrapper.in(StoreComment::getStoreId, storeIds)
+                    .eq(StoreComment::getBusinessType, 5)
+                    .eq(StoreComment::getDeleteFlag, 0)
+                    .isNull(StoreComment::getReplyId);
+            List<StoreComment> totalComments = storeCommentMapper.selectList(totalCommentWrapper);
+            Map<Integer, Long> tempTotalCommentMap = totalComments.stream()
+                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
+            totalCommentMap.putAll(tempTotalCommentMap);
+        }
+
+        // 获取全部店铺的评分
+        Map<String, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
+                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
+        Map<String, List<Map<String, Object>>> avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream()
+                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
+
+        // 计算综合得分并排序
+        List<StoreInfoVo> sortedList = storeInfoVoList.stream()
+                .map(store -> {
+                    // 获取基础评分(score_avg × 2,标准化为0-10分)
+                    Double scoreAvg = store.getScoreAvg() != null ? store.getScoreAvg() : 0.0;
+                    double baseScore = Math.min(scoreAvg * 2, 10.0); // 基础评分,最高10分
+
+                    // 获取距离
+                    double storeDistance = 999999;
+                    try {
+                        String distStr = store.getDist();
+                        if (distStr != null && !distStr.isEmpty()) {
+                            storeDistance = Double.parseDouble(distStr);
+                        }
+                    } catch (NumberFormatException e) {
+                        // 忽略
+                    }
+
+                    double finalScore = 0.0;
+
+                    if (finalSortType == 1) {
+                        // 智能排序:综合评分×50% + 近7天销量×30% + 距离得分×20%
+                        // 综合评分(基础评分)
+                        double scorePart = baseScore * 0.5;
+
+                        // 近7天销量(需要标准化,假设最大销量为100)
+                        long sales7Days = sales7DaysMap.getOrDefault(store.getId(), 0L);
+                        double salesScore = Math.min(sales7Days / 100.0 * 10, 10.0); // 标准化到0-10
+                        double salesPart = salesScore * 0.3;
+
+                        // 距离得分(距离越近得分越高,10公里内计算)
+                        double distanceScore = storeDistance <= 10 ? (10 - storeDistance) / 10.0 * 10 : 0;
+                        double distancePart = distanceScore * 0.2;
+
+                        finalScore = scorePart + salesPart + distancePart;
+                    } else if (finalSortType == 2) {
+                        // 好评优先:综合评分×50% + 近30天好评数×35% + 近7天新评占比×15%
+                        double scorePart = baseScore * 0.5;
+
+                        // 近30天好评数(需要标准化,假设最大好评数为50)
+                        long goodComment30Days = goodComment30DaysMap.getOrDefault(store.getId(), 0L);
+                        double goodCommentScore = Math.min(goodComment30Days / 50.0 * 10, 10.0);
+                        double goodCommentPart = goodCommentScore * 0.35;
+
+                        // 近7天新评占比
+                        long comment7Days = comment7DaysMap.getOrDefault(store.getId(), 0L);
+                        long totalComment = totalCommentMap.getOrDefault(store.getId(), 1L); // 避免除0
+                        double newCommentRatio = (double) comment7Days / totalComment;
+                        double newCommentPart = newCommentRatio * 10 * 0.15; // 占比转换为0-10分
+
+                        finalScore = scorePart + goodCommentPart + newCommentPart;
+                    } else if (finalSortType == 3) {
+                        // 距离优先:距离得分 = (10 - 实际距离) × 80% + 基础评分 × 20%(10公里内计算)
+                        if (storeDistance <= 10) {
+                            double distanceScore = (10 - storeDistance) / 10.0 * 10; // 标准化到0-10
+                            double distancePart = distanceScore * 0.8;
+                            double scorePart = baseScore * 0.2;
+                            finalScore = distancePart + scorePart;
+                        } else {
+                            finalScore = -1; // 超出范围,不展示
+                        }
+                    }
+
+                    // 设置综合得分(用于排序)
+                    store.setDistance(storeDistance);
+                    // 使用反射或扩展字段存储finalScore,这里我们使用一个临时字段
+                    // 由于StoreInfoVo没有finalScore字段,我们使用distance字段临时存储,排序后再恢复
+                    return new Object[] { store, finalScore };
+                })
+                .filter(item -> {
+                    // 距离优先模式:过滤掉超出范围的
+                    if (finalSortType == 3) {
+                        return ((Double) item[1]) >= 0;
+                    }
+                    return true;
+                })
+                .sorted((a, b) -> Double.compare((Double) b[1], (Double) a[1])) // 按得分降序
+                .map(item -> (StoreInfoVo) item[0])
+                .collect(Collectors.toList());
+
+        // 分页处理
+        long total = sortedList.size();
+        int start = (pageNum - 1) * pageSize;
+        int end = Math.min(start + pageSize, sortedList.size());
+        List<StoreInfoVo> pagedList;
+        if (start < sortedList.size()) {
+            pagedList = sortedList.subList(start, end);
+        } else {
+            pagedList = new ArrayList<>();
+        }
+
+        // 查询每个店铺的最新代金券(只显示一个,最新创建的)
+        Map<Integer, LifeCoupon> latestCouponMap = new HashMap<>();
+        if (!CollectionUtils.isEmpty(pagedList)) {
+            List<Integer> pagedStoreIds = pagedList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
+            // 查询所有店铺的代金券,按创建时间降序
+            LambdaQueryWrapper<LifeCoupon> couponWrapper = new LambdaQueryWrapper<>();
+            couponWrapper.in(LifeCoupon::getStoreId, pagedStoreIds.stream().map(String::valueOf).collect(Collectors.toList()))
+                    .eq(LifeCoupon::getStatus, CouponStatusEnum.ONGOING.getCode())
+                    .eq(LifeCoupon::getType, 1) // 代金券类型
+                    .eq(LifeCoupon::getDeleteFlag, 0)
+                    .orderByDesc(LifeCoupon::getCreatedTime);
+            List<LifeCoupon> allCoupons = lifeCouponMapper.selectList(couponWrapper);
+
+            // 为每个店铺只保留最新创建的一个代金券
+            for (LifeCoupon coupon : allCoupons) {
+                if (coupon.getStoreId() != null) {
+                    try {
+                        Integer storeId = Integer.parseInt(coupon.getStoreId());
+                        // 如果该店铺还没有代金券,或者当前代金券更新,则更新
+                        if (!latestCouponMap.containsKey(storeId)) {
+                            latestCouponMap.put(storeId, coupon);
+                        }
+                    } catch (NumberFormatException e) {
+                        // 忽略无效的storeId
+                    }
+                }
+            }
+        }
+
+        // 设置评分、平均消费和代金券
+        for (StoreInfoVo store : pagedList) {
+            if (avgScoreMap.containsKey(String.valueOf(store.getId()))) {
+                store.setAvgScore(new BigDecimal(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score").toString())
+                        .setScale(1, RoundingMode.HALF_UP).toString());
+                store.setTotalNum(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num").toString());
+            } else {
+                store.setAvgScore("0");
+                store.setTotalNum("0");
+            }
+
+            if (avgPriceMap.containsKey(String.valueOf(store.getId()))) {
+                store.setAvgPrice(avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price").toString());
+            } else {
+                store.setAvgPrice("0");
+            }
+
+            // 设置最新代金券(只显示一个)
+            if (latestCouponMap.containsKey(store.getId())) {
+                LifeCoupon latestCoupon = latestCouponMap.get(store.getId());
+                LifeCouponVo couponVo = new LifeCouponVo();
+                BeanUtils.copyProperties(latestCoupon, couponVo);
+                // 只设置一个代金券到列表中
+                List<LifeCouponVo> couponList = new ArrayList<>();
+                couponList.add(couponVo);
+                store.setCouponList(couponList);
+            } else {
+                // 如果没有代金券,设置为空列表
+                store.setCouponList(new ArrayList<>());
+            }
+        }
+
+        // 创建分页对象
+        IPage<StoreInfoVo> resultPage = new Page<>(pageNum, pageSize);
+        resultPage.setRecords(pagedList);
+        resultPage.setTotal(total);
+        resultPage.setCurrent(pageNum);
+        resultPage.setSize(pageSize);
+        resultPage.setPages((total + pageSize - 1) / pageSize);
+
+        return resultPage;
+    }
+
+
+
+
+    /**
+     * 你可能还喜欢(推荐店铺)
+     * 根据一级分类、二级分类、三级分类进行店铺筛选
+     * 筛选顺序:先三级,然后二级,最后一级
+     *
+     * @param businessSection 一级分类(经营板块)
+     * @param businessTypes 二级分类(经营种类)
+     * @param businessClassify 三级分类(分类)
+     * @param lon 经度
+     * @param lat 纬度
+     * @return List<StoreInfoVo> 店铺信息列表
+     */
+    @Override
+    public List<StoreInfoVo> getRecommendedStores(String businessSection, String businessTypes, String businessClassify, Double lon, Double lat) {
+        log.info("StoreInfoServiceImpl.getRecommendedStores?businessSection={},businessTypes={},businessClassify={},lon={},lat={}",
+                businessSection, businessTypes, businessClassify, lon, lat);
+
+        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
+        // 基础条件:未删除、已启用
+        queryWrapper.eq("a.delete_flag", 0)
+                .eq("b.delete_flag", 0)
+                .ne("a.business_status", 99) // 过滤永久关门的店铺
+                .ne("a.store_status", 0); // 过滤禁用的店铺
+
+        // 按照三级->二级->一级的顺序筛选
+
+        // 1. 先按三级分类(business_classify)筛选
+        if (StringUtils.isNotEmpty(businessClassify)) {
+            // 解析businessClassify参数(格式:1,2,3)
+            String[] classifyArray = businessClassify.split(",");
+            // 使用FIND_IN_SET函数检查数据库字段是否包含参数中的任何一个值
+            queryWrapper.and(wrapper -> {
+                for (int i = 0; i < classifyArray.length; i++) {
+                    String classify = classifyArray[i].trim();
+                    if (StringUtils.isNotEmpty(classify)) {
+                        if (i == 0) {
+                            wrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", classify);
+                        } else {
+                            wrapper.or().apply("FIND_IN_SET({0}, a.business_classify) > 0", classify);
+                        }
+                    }
+                }
+            });
+        }
+
+        // 2. 然后按二级分类(business_types)筛选
+        if (StringUtils.isNotEmpty(businessTypes)) {
+            // business_types可能是逗号分隔的字符串,使用FIND_IN_SET处理
+            String[] typesArray = businessTypes.split(",");
+            queryWrapper.and(wrapper -> {
+                for (int i = 0; i < typesArray.length; i++) {
+                    String type = typesArray[i].trim();
+                    if (StringUtils.isNotEmpty(type)) {
+                        if (i == 0) {
+                            wrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", type);
+                        } else {
+                            wrapper.or().apply("FIND_IN_SET({0}, a.business_types) > 0", type);
+                        }
+                    }
+                }
+            });
+        }
+
+        // 3. 最后按一级分类(business_section)筛选
+        if (StringUtils.isNotEmpty(businessSection)) {
+            try {
+                Integer sectionId = Integer.parseInt(businessSection.trim());
+                queryWrapper.eq("a.business_section", sectionId);
+            } catch (NumberFormatException e) {
+                log.warn("一级分类参数格式错误: {}", businessSection);
+            }
+        }
+
+        // 查询店铺列表
+        List<StoreInfoVo> storeInfoVoList;
+        if (lon != null && lat != null) {
+            // 如果提供了经纬度,使用带距离计算的查询方法
+            String position = lon + "," + lat;
+            queryWrapper.isNotNull("a.store_position")
+                    .ne("a.store_position", "");
+            // 按距离排序
+            queryWrapper.orderByAsc("dist");
+            storeInfoVoList = storeInfoMapper.getStoreInfoVoListNew(queryWrapper, position);
+        } else {
+            // 如果没有提供经纬度,使用普通查询方法
+            queryWrapper.orderByDesc("a.created_time");
+            storeInfoVoList = storeInfoMapper.getStoreInfoVoList(queryWrapper);
+        }
+
+        if (CollectionUtils.isEmpty(storeInfoVoList)) {
+            return Collections.emptyList();
+        }
+
+        // 处理店铺信息,设置评分等
+        // 提前查询所有需要的字典数据
+        List<StoreInfoVo> collect = storeInfoVoList.stream()
+                .filter(record -> StringUtils.isNotEmpty(record.getStoreType()))
+                .collect(Collectors.toList());
+        Set<String> allTypes = collect.stream()
+                .map(StoreInfoVo::getStoreType)
+                .flatMap(type -> Arrays.stream(type.split(",")))
+                .collect(Collectors.toSet());
+
+        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
+                new LambdaQueryWrapper<StoreDictionary>()
+                        .eq(StoreDictionary::getTypeName, "storeType")
+                        .isNull(StoreDictionary::getParentId)
+                        .in(!allTypes.isEmpty(), StoreDictionary::getDictId, allTypes));
+        Map<String, String> typeMap = storeDictionaries.stream()
+                .collect(Collectors.toMap(StoreDictionary::getDictId, StoreDictionary::getDictDetail));
+
+        // 计算平均分和评价
+        Map<String, List<Map<String, Object>>> avgScoreMap = new HashMap<>();
+        Map<Integer, List<StoreComment>> commentMap = new HashMap<>();
+
+        avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
+                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
+        commentMap = storeCommentMapper.selectList(
+                        new QueryWrapper<StoreComment>()
+                                .eq("business_type", "5")
+                                .eq("delete_flag", 0))
+                .stream()
+                .collect(Collectors.groupingBy(StoreComment::getStoreId));
+
+        for (StoreInfoVo record : storeInfoVoList) {
+            // 处理类型
+            if (StringUtils.isNotEmpty(record.getStoreType())) {
+                String[] types = record.getStoreType().split(",");
+                List<String> typeDetails = Arrays.stream(types)
+                        .map(typeMap::get)
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
+                record.setStoreTypeStr(String.join(",", typeDetails));
+                record.setStoreTypeList(Arrays.asList(types));
+            }
+
+            // 处理经纬度
+            if (StringUtils.isNotEmpty(record.getStorePosition())) {
+                String[] split = record.getStorePosition().split(",");
+                if (split.length >= 2) {
+                    record.setStorePositionLongitude(split[0]);
+                    record.setStorePositionLatitude(split[1]);
+                }
+            }
+
+            // 如果提供了经纬度,处理距离信息
+            if (lon != null && lat != null && StringUtils.isNotEmpty(record.getStorePosition())) {
+                try {
+                    // 手动计算距离(单位:公里)
+                    String[] positionArray = record.getStorePosition().split(",");
+                    if (positionArray.length >= 2) {
+                        double storeLon = Double.parseDouble(positionArray[0].trim());
+                        double storeLat = Double.parseDouble(positionArray[1].trim());
+                        // 计算距离(单位:公里)
+                        double distanceKm = DistanceUtil.haversineCalculateDistance(lon, lat, storeLon, storeLat);
+                        record.setDistance(distanceKm);
+                    }
+                } catch (Exception e) {
+                    log.warn("计算店铺距离失败,storeId={},error={}", record.getId(), e.getMessage());
+                }
+            }
+
+            // 处理到期状态
+            Date expirationTime = record.getExpirationTime();
+            if (expirationTime != null) {
+                Date currentDate = new Date();
+                Calendar now = Calendar.getInstance();
+                Date nowCurrentDate = now.getTime();
+                now.add(Calendar.DAY_OF_YEAR, 30);
+                Date thirtyDaysLater = now.getTime();
+
+                if (expirationTime.after(currentDate)) {
+                    record.setExpiredState("0");
+                    if ((expirationTime.after(nowCurrentDate) || expirationTime.equals(nowCurrentDate))
+                            && expirationTime.before(thirtyDaysLater)) {
+                        record.setExpiredState("1");
+                    }
+                } else {
+                    record.setExpiredState("2");
+                }
+
+                LocalDate nowLocal = LocalDate.now();
+                LocalDate expDate = expirationTime.toInstant()
+                        .atZone(ZoneId.systemDefault())
+                        .toLocalDate();
+                long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
+                record.setDaysToExpire(daysToExpire);
+            }
+
+            // 设置店铺得分和总评论数
+            if (avgScoreMap.containsKey(String.valueOf(record.getId()))) {
+                record.setAvgScore(String.valueOf(
+                        avgScoreMap.get(String.valueOf(record.getId())).get(0).get("avg_score")));
+            }
+            if (commentMap.containsKey(record.getId())) {
+                record.setTotalNum(String.valueOf(commentMap.get(record.getId()).size()));
+            }
+        }
+
+        return storeInfoVoList;
+    }
+
+
+
+    /**
+     * 构建树形结构(优化版)
+     *
+     * @param flatList 扁平列表
+     * @return 树形结构列表
+     */
+    private List<StoreDictionary> buildTreeOptimized(List<StoreDictionary> flatList) {
+        if (flatList == null || flatList.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // 创建三个存储结构
+        Map<Integer, StoreDictionary> nodeMap = new HashMap<>();  // ID到节点的映射
+        Map<Integer, List<StoreDictionary>> parentChildMap = new HashMap<>();  // 父ID到子节点列表的映射
+        List<StoreDictionary> result = new ArrayList<>();  // 结果列表
+
+        // 填充nodeMap和parentChildMap
+        for (StoreDictionary entity : flatList) {
+            Integer id = entity.getId();
+            Integer parentId = entity.getParentId();
+
+            // 存入节点映射
+            nodeMap.put(id, entity);
+
+            // 初始化子节点列表
+            entity.setStoreDictionaryList(new ArrayList<>());
+
+            // 如果是根节点(parentId为null或0),直接添加到结果
+            if (parentId == null || parentId == 0) {
+                result.add(entity);
+            } else {
+                // 否则,记录父子关系
+                parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(entity);
+            }
+        }
+
+        // 建立父子关系
+        for (StoreDictionary entity : flatList) {
+            Integer id = entity.getId();
+            if (parentChildMap.containsKey(id)) {
+                entity.getStoreDictionaryList().addAll(parentChildMap.get(id));
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<StoreDictionaryVo> getLeisureEntertainmentCategories() {
+        // 定义四种主分类名称
+        List<String> mainCategoryNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
+
+        // 查询所有主分类(business_section类型)
+        List<StoreDictionary> allMainCategories = storeDictionaryMapper.selectList(
+                new LambdaQueryWrapper<StoreDictionary>()
+                        .eq(StoreDictionary::getTypeName, "business_section")
+                        .in(StoreDictionary::getDictDetail, mainCategoryNames)
+                        .eq(StoreDictionary::getDeleteFlag, 0)
+        );
+
+        // 构建主分类列表,包含"全部"选项
+        List<StoreDictionaryVo> result = new ArrayList<>();
+
+        // 添加"全部"选项
+        StoreDictionaryVo allCategory = new StoreDictionaryVo();
+        allCategory.setId(0);
+        allCategory.setDictId("0");
+        allCategory.setDictDetail("全部");
+        allCategory.setTypeName("business_section");
+        allCategory.setSubDataList(new ArrayList<>());
+        result.add(allCategory);
+
+        // 查询所有子分类(根据parent_id关联)
+        Map<Integer, List<StoreDictionary>> subCategoryMap = new HashMap<>();
+        if (!CollectionUtils.isEmpty(allMainCategories)) {
+            List<Integer> mainCategoryIds = allMainCategories.stream()
+                    .map(StoreDictionary::getId)
+                    .collect(Collectors.toList());
+
+            // 查询所有子分类
+            List<StoreDictionary> allSubCategories = storeDictionaryMapper.selectList(
+                    new LambdaQueryWrapper<StoreDictionary>()
+                            .in(StoreDictionary::getParentId, mainCategoryIds)
+                            .eq(StoreDictionary::getDeleteFlag, 0)
+                            .in(StoreDictionary::getTypeName, "business_section","business_type","business_classify")
+            );
+
+            // 按parentId分组
+            subCategoryMap = allSubCategories.stream()
+                    .collect(Collectors.groupingBy(StoreDictionary::getParentId));
+        }
+
+        // 构建主分类及其子分类
+        for (StoreDictionary mainCategory : allMainCategories) {
+            StoreDictionaryVo mainVo = new StoreDictionaryVo();
+            BeanUtils.copyProperties(mainCategory, mainVo);
+
+            // 获取该主分类下的子分类
+            List<StoreDictionary> subCategories = subCategoryMap.getOrDefault(mainCategory.getId(), new ArrayList<>());
+            List<StoreDictionaryVo> subVoList = new ArrayList<>();
+
+            for (StoreDictionary subCategory : subCategories) {
+                StoreDictionaryVo subVo = new StoreDictionaryVo();
+                BeanUtils.copyProperties(subCategory, subVo);
+                subVoList.add(subVo);
+            }
+
+            mainVo.setSubDataList(subVoList);
+            result.add(mainVo);
+        }
+
+        return result;
+    }
+
+
+    @Override
+    public IPage<StoreInfoVo> getSpecialTypeStoresByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, int pageNum, int pageSize) {
+        // 参数校验
+        if (lon == null || lat == null) {
+            throw new IllegalArgumentException("经纬度参数不能为空");
+        }
+
+        // 智能检测:如果参数可能传反了(lat超出范围但lon在范围内),给出提示
+        if (Math.abs(lat) > 90 && Math.abs(lon) <= 90) {
+            throw new IllegalArgumentException(
+                    String.format("参数可能传反了!当前值: lon=%s, lat=%s。经度范围: [-180, 180],纬度范围: [-90, 90]。请检查参数顺序。", lon, lat)
+            );
+        }
+
+        // 校验经纬度范围:经度 [-180, 180],纬度 [-90, 90]
+        if (lon < -180 || lon > 180) {
+            throw new IllegalArgumentException("经度参数超出有效范围 [-180, 180],当前值: " + lon);
+        }
+        if (lat < -90 || lat > 90) {
+            throw new IllegalArgumentException("纬度参数超出有效范围 [-90, 90],当前值: " + lat);
+        }
+        final int finalSortType = (sortType == null || sortType < 1 || sortType > 3) ? 1 : sortType; // 默认智能排序
+        if (pageNum <= 0) {
+            pageNum = 1;
+        }
+        if (pageSize <= 0) {
+            pageSize = 10;
+        }
+
+        // 构建查询条件
+        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
+
+        // 如果传入了dictId,根据字典id查询经营板块、经营种类、分类并匹配店铺
+        if (categoryId != null) {
+            // 根据categoryId查询字典表记录
+            StoreDictionary dict = storeDictionaryMapper.selectById(categoryId);
+            if (dict == null || dict.getDeleteFlag() == 1) {
+                throw new IllegalArgumentException("字典id不存在或已删除: " + categoryId);
+            }
+
+            String typeName = dict.getTypeName();
+            String dictIdStr =dict.getDictId();
+
+            if ("business_section".equals(typeName)) {
+                // 如果是经营板块,直接匹配business_section
+                try {
+                    Integer sectionId = Integer.parseInt(dictIdStr);
+                    queryWrapper.eq("a.business_section", sectionId);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException("经营板块dictId格式错误: " + dictIdStr);
+                }
+            } else if ("business_type".equals(typeName)) {
+                // 如果是经营种类,需要:
+                // 1. 向上查找父级(经营板块)
+                // 2. 匹配business_section和business_types
+                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
+                if (parentDict == null || !"business_section".equals(parentDict.getTypeName())) {
+                    throw new IllegalArgumentException("经营种类的父级不是经营板块,categoryId: " + categoryId);
+                }
+
+                try {
+                    Integer sectionId = Integer.parseInt(parentDict.getDictId());
+                    queryWrapper.eq("a.business_section", sectionId);
+                    // 使用FIND_IN_SET匹配business_types字段(逗号分隔)
+                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", dictIdStr);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException("经营板块或经营种类dictId格式错误");
+                }
+            } else if ("business_classify".equals(typeName)) {
+                // 如果是分类,需要:
+                // 1. 向上查找父级(经营种类)
+                // 2. 向上查找祖父级(经营板块)
+                // 3. 匹配business_section、business_types和business_classify
+                StoreDictionary parentDict = storeDictionaryMapper.selectById(dict.getParentId());
+                if (parentDict == null || !"business_type".equals(parentDict.getTypeName())) {
+                    throw new IllegalArgumentException("分类的父级不是经营种类,categoryId: " + categoryId);
+                }
+
+                StoreDictionary grandParentDict = storeDictionaryMapper.selectById(parentDict.getParentId());
+                if (grandParentDict == null || !"business_section".equals(grandParentDict.getTypeName())) {
+                    throw new IllegalArgumentException("经营种类的父级不是经营板块,categoryId: " + categoryId);
+                }
+
+                try {
+                    Integer sectionId = Integer.parseInt(grandParentDict.getDictId());
+                    queryWrapper.eq("a.business_section", sectionId);
+                    // 使用FIND_IN_SET匹配business_types字段
+                    queryWrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", parentDict.getDictId());
+                    // 使用FIND_IN_SET匹配business_classify字段
+                    queryWrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", dictIdStr);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException("经营板块、经营种类或分类dictId格式错误");
+                }
+            } else {
+                throw new IllegalArgumentException("不支持的字典类型: " + typeName + ", categoryId: " + categoryId);
+            }
+        } else if (businessType != null) {
+            // 如果指定了businessType,则根据传入的数值进行筛选
+            // 直接使用传入的数值作为business_section进行筛选
+            // KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧的数值未知(由调用方传入)
+            queryWrapper.eq("a.business_section", businessType);
+        } else {
+            // 如果没有指定businessType,则查询所有四种类型的店铺
+            // 需要查询字典表获取所有四种类型的dictId
+            List<String> storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
+            List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
+                    new LambdaQueryWrapper<StoreDictionary>()
+                            .eq(StoreDictionary::getTypeName, "business_section")
+                            .in(StoreDictionary::getDictDetail, storeTypeNames)
+                            .eq(StoreDictionary::getDeleteFlag, 0)
+            );
+
+            List<Integer> businessSectionIds = storeDictionaries.stream()
+                    .filter(d -> StringUtils.isNotEmpty(d.getDictId()))
+                    .map(StoreDictionary::getDictId)
+                    .map(dictIdStr -> {
+                        try {
+                            return Integer.parseInt(dictIdStr);
+                        } catch (NumberFormatException e) {
+                            return null;
+                        }
+                    })
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+
+            // 使用business_section字段进行筛选
+            queryWrapper.in("a.business_section", businessSectionIds);
+        }
+
+        // 过滤已删除的门店
+        queryWrapper.eq("a.delete_flag", 0);
+        // 过滤注销的门店
+        queryWrapper.eq("a.logout_flag", 0);
+        // 过滤禁用的门店
+        queryWrapper.ne("a.store_status", 0);
+        // 过滤永久关门的店铺
+        queryWrapper.ne("a.business_status", 99);
+        // 过滤过期的经营许可证
+        queryWrapper.ge("a.entertainment_licence_expiration_time", new Date());
+
+        // 距离优先模式:只显示10公里内且3.5星以上的店铺
+        final Double finalDistance;
+        if (finalSortType == 3) {
+            queryWrapper.ge("a.score_avg", 3.5);
+            if (distance == null || distance <= 0) {
+                finalDistance = 10.0; // 默认10公里
+            } else if (distance > 10) {
+                finalDistance = 10.0; // 距离优先最多10公里
+            } else {
+                finalDistance = distance;
+            }
+        } else {
+            finalDistance = distance;
+        }
+
+        // 先按距离排序获取所有数据(用于计算距离)
+        queryWrapper.orderByAsc("dist");
+
+        // 创建分页对象(先获取更多数据用于排序计算)
+        IPage<StoreInfoVo> page = new Page<>(1, 1000); // 先获取足够多的数据
+        IPage<StoreInfoVo> storeInfoIPage = storeInfoMapper.getPageForDistance(page, lon + "," + lat, queryWrapper);
+        List<StoreInfoVo> storeInfoVoList = storeInfoIPage.getRecords();
+
+        // 如果指定了距离范围,进行距离筛选
+        if (finalDistance != null && finalDistance > 0) {
+            storeInfoVoList = storeInfoVoList.stream()
+                    .filter(store -> {
+                        String distStr = store.getDist();
+                        if (distStr == null || distStr.isEmpty()) {
+                            return false;
+                        }
+                        try {
+                            double storeDistance = Double.parseDouble(distStr);
+                            return storeDistance <= finalDistance;
+                        } catch (NumberFormatException e) {
+                            return false;
+                        }
+                    })
+                    .collect(Collectors.toList());
+        }
+
+        // 计算时间范围
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime sevenDaysAgo = now.minusDays(7);
+        LocalDateTime thirtyDaysAgo = now.minusDays(30);
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String sevenDaysAgoStr = sevenDaysAgo.format(formatter);
+        String thirtyDaysAgoStr = thirtyDaysAgo.format(formatter);
+
+        // 提取所有门店ID
+        List<Integer> storeIds = storeInfoVoList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
+
+        if (CollectionUtils.isEmpty(storeIds)) {
+            // 如果没有符合条件的店铺,返回空结果
+            IPage<StoreInfoVo> emptyPage = new Page<>(pageNum, pageSize);
+            emptyPage.setRecords(new ArrayList<>());
+            emptyPage.setTotal(0);
+            return emptyPage;
+        }
+
+        // 查询近7天销量(订单数)
+        Map<Integer, Long> sales7DaysMap = new HashMap<>();
+        if (finalSortType == 1) { // 智能排序需要销量数据
+            LambdaQueryWrapper<LifeUserOrder> orderWrapper = new LambdaQueryWrapper<>();
+            orderWrapper.in(LifeUserOrder::getStoreId, storeIds)
+                    .and(w -> w.and(w1 -> w1.eq(LifeUserOrder::getStatus, 7)
+                                    .ge(LifeUserOrder::getFinishTime, sevenDaysAgoStr))
+                            .or(w2 -> w2.eq(LifeUserOrder::getStatus, 1)
+                                    .ge(LifeUserOrder::getPayTime, sevenDaysAgoStr)))
+                    .eq(LifeUserOrder::getDeleteFlag, 0);
+            List<LifeUserOrder> orders7Days = lifeUserOrderMapper.selectList(orderWrapper);
+            Map<Integer, Long> tempSalesMap = orders7Days.stream()
+                    .filter(order -> order.getStoreId() != null)
+                    .collect(Collectors.groupingBy(
+                            order -> Integer.parseInt(order.getStoreId()),
+                            Collectors.counting()));
+            sales7DaysMap.putAll(tempSalesMap);
+        }
+
+        // 查询近30天好评数(score >= 4.5)
+        Map<Integer, Long> goodComment30DaysMap = new HashMap<>();
+        // 查询近7天评论数
+        Map<Integer, Long> comment7DaysMap = new HashMap<>();
+        // 查询总评论数
+        Map<Integer, Long> totalCommentMap = new HashMap<>();
+
+        if (finalSortType == 2) { // 好评优先需要评论数据
+            // 近30天好评数
+            LambdaQueryWrapper<StoreComment> goodCommentWrapper = new LambdaQueryWrapper<>();
+            goodCommentWrapper.in(StoreComment::getStoreId, storeIds)
+                    .eq(StoreComment::getBusinessType, 5)
+                    .eq(StoreComment::getDeleteFlag, 0)
+                    .isNull(StoreComment::getReplyId)
+                    .ge(StoreComment::getScore, 4.5)
+                    .ge(StoreComment::getCreatedTime, thirtyDaysAgoStr);
+            List<StoreComment> goodComments30Days = storeCommentMapper.selectList(goodCommentWrapper);
+            Map<Integer, Long> tempGoodCommentMap = goodComments30Days.stream()
+                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
+            goodComment30DaysMap.putAll(tempGoodCommentMap);
+
+            // 近7天评论数
+            LambdaQueryWrapper<StoreComment> comment7DaysWrapper = new LambdaQueryWrapper<>();
+            comment7DaysWrapper.in(StoreComment::getStoreId, storeIds)
+                    .eq(StoreComment::getBusinessType, 5)
+                    .eq(StoreComment::getDeleteFlag, 0)
+                    .isNull(StoreComment::getReplyId)
+                    .ge(StoreComment::getCreatedTime, sevenDaysAgoStr);
+            List<StoreComment> comments7Days = storeCommentMapper.selectList(comment7DaysWrapper);
+            Map<Integer, Long> tempComment7DaysMap = comments7Days.stream()
+                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
+            comment7DaysMap.putAll(tempComment7DaysMap);
+
+            // 总评论数
+            LambdaQueryWrapper<StoreComment> totalCommentWrapper = new LambdaQueryWrapper<>();
+            totalCommentWrapper.in(StoreComment::getStoreId, storeIds)
+                    .eq(StoreComment::getBusinessType, 5)
+                    .eq(StoreComment::getDeleteFlag, 0)
+                    .isNull(StoreComment::getReplyId);
+            List<StoreComment> totalComments = storeCommentMapper.selectList(totalCommentWrapper);
+            Map<Integer, Long> tempTotalCommentMap = totalComments.stream()
+                    .collect(Collectors.groupingBy(StoreComment::getStoreId, Collectors.counting()));
+            totalCommentMap.putAll(tempTotalCommentMap);
+        }
+
+        // 获取全部店铺的评分
+        Map<String, List<Map<String, Object>>> avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
+                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
+        Map<String, List<Map<String, Object>>> avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream()
+                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
+
+        // 计算综合得分并排序
+        List<StoreInfoVo> sortedList = storeInfoVoList.stream()
+                .map(store -> {
+                    // 获取基础评分(score_avg × 2,标准化为0-10分)
+                    Double scoreAvg = store.getScoreAvg() != null ? store.getScoreAvg() : 0.0;
+                    double baseScore = Math.min(scoreAvg * 2, 10.0); // 基础评分,最高10分
+
+                    // 获取距离
+                    double storeDistance = 999999;
+                    try {
+                        String distStr = store.getDist();
+                        if (distStr != null && !distStr.isEmpty()) {
+                            storeDistance = Double.parseDouble(distStr);
+                        }
+                    } catch (NumberFormatException e) {
+                        // 忽略
+                    }
+
+                    double finalScore = 0.0;
+
+                    if (finalSortType == 1) {
+                        // 智能排序:综合评分×50% + 近7天销量×30% + 距离得分×20%
+                        // 综合评分(基础评分)
+                        double scorePart = baseScore * 0.5;
+
+                        // 近7天销量(需要标准化,假设最大销量为100)
+                        long sales7Days = sales7DaysMap.getOrDefault(store.getId(), 0L);
+                        double salesScore = Math.min(sales7Days / 100.0 * 10, 10.0); // 标准化到0-10
+                        double salesPart = salesScore * 0.3;
+
+                        // 距离得分(距离越近得分越高,10公里内计算)
+                        double distanceScore = storeDistance <= 10 ? (10 - storeDistance) / 10.0 * 10 : 0;
+                        double distancePart = distanceScore * 0.2;
+
+                        finalScore = scorePart + salesPart + distancePart;
+                    } else if (finalSortType == 2) {
+                        // 好评优先:综合评分×50% + 近30天好评数×35% + 近7天新评占比×15%
+                        double scorePart = baseScore * 0.5;
+
+                        // 近30天好评数(需要标准化,假设最大好评数为50)
+                        long goodComment30Days = goodComment30DaysMap.getOrDefault(store.getId(), 0L);
+                        double goodCommentScore = Math.min(goodComment30Days / 50.0 * 10, 10.0);
+                        double goodCommentPart = goodCommentScore * 0.35;
+
+                        // 近7天新评占比
+                        long comment7Days = comment7DaysMap.getOrDefault(store.getId(), 0L);
+                        long totalComment = totalCommentMap.getOrDefault(store.getId(), 1L); // 避免除0
+                        double newCommentRatio = (double) comment7Days / totalComment;
+                        double newCommentPart = newCommentRatio * 10 * 0.15; // 占比转换为0-10分
+
+                        finalScore = scorePart + goodCommentPart + newCommentPart;
+                    } else if (finalSortType == 3) {
+                        // 距离优先:距离得分 = (10 - 实际距离) × 80% + 基础评分 × 20%(10公里内计算)
+                        if (storeDistance <= 10) {
+                            double distanceScore = (10 - storeDistance) / 10.0 * 10; // 标准化到0-10
+                            double distancePart = distanceScore * 0.8;
+                            double scorePart = baseScore * 0.2;
+                            finalScore = distancePart + scorePart;
+                        } else {
+                            finalScore = -1; // 超出范围,不展示
+                        }
+                    }
+
+                    // 设置综合得分(用于排序)
+                    store.setDistance(storeDistance);
+                    // 使用反射或扩展字段存储finalScore,这里我们使用一个临时字段
+                    // 由于StoreInfoVo没有finalScore字段,我们使用distance字段临时存储,排序后再恢复
+                    return new Object[] { store, finalScore };
+                })
+                .filter(item -> {
+                    // 距离优先模式:过滤掉超出范围的
+                    if (finalSortType == 3) {
+                        return ((Double) item[1]) >= 0;
+                    }
+                    return true;
+                })
+                .sorted((a, b) -> Double.compare((Double) b[1], (Double) a[1])) // 按得分降序
+                .map(item -> (StoreInfoVo) item[0])
+                .collect(Collectors.toList());
+
+        // 分页处理
+        long total = sortedList.size();
+        int start = (pageNum - 1) * pageSize;
+        int end = Math.min(start + pageSize, sortedList.size());
+        List<StoreInfoVo> pagedList;
+        if (start < sortedList.size()) {
+            pagedList = sortedList.subList(start, end);
+        } else {
+            pagedList = new ArrayList<>();
+        }
+
+        // 查询每个店铺的最新代金券(只显示一个,最新创建的)
+        Map<Integer, LifeCoupon> latestCouponMap = new HashMap<>();
+        if (!CollectionUtils.isEmpty(pagedList)) {
+            List<Integer> pagedStoreIds = pagedList.stream().map(StoreInfoVo::getId).collect(Collectors.toList());
+            // 查询所有店铺的代金券,按创建时间降序
+            LambdaQueryWrapper<LifeCoupon> couponWrapper = new LambdaQueryWrapper<>();
+            couponWrapper.in(LifeCoupon::getStoreId, pagedStoreIds.stream().map(String::valueOf).collect(Collectors.toList()))
+                    .eq(LifeCoupon::getStatus, CouponStatusEnum.ONGOING.getCode())
+                    .eq(LifeCoupon::getType, 1) // 代金券类型
+                    .eq(LifeCoupon::getDeleteFlag, 0)
+                    .orderByDesc(LifeCoupon::getCreatedTime);
+            List<LifeCoupon> allCoupons = lifeCouponMapper.selectList(couponWrapper);
+
+            // 为每个店铺只保留最新创建的一个代金券
+            for (LifeCoupon coupon : allCoupons) {
+                if (coupon.getStoreId() != null) {
+                    try {
+                        Integer storeId = Integer.parseInt(coupon.getStoreId());
+                        // 如果该店铺还没有代金券,或者当前代金券更新,则更新
+                        if (!latestCouponMap.containsKey(storeId)) {
+                            latestCouponMap.put(storeId, coupon);
+                        }
+                    } catch (NumberFormatException e) {
+                        // 忽略无效的storeId
+                    }
+                }
+            }
+        }
+
+        // 设置评分、平均消费和代金券
+        for (StoreInfoVo store : pagedList) {
+            if (avgScoreMap.containsKey(String.valueOf(store.getId()))) {
+                store.setAvgScore(new BigDecimal(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("avg_score").toString())
+                        .setScale(1, RoundingMode.HALF_UP).toString());
+                store.setTotalNum(avgScoreMap.get(String.valueOf(store.getId())).get(0).get("total_num").toString());
+            } else {
+                store.setAvgScore("0");
+                store.setTotalNum("0");
+            }
+
+            if (avgPriceMap.containsKey(String.valueOf(store.getId()))) {
+                store.setAvgPrice(avgPriceMap.get(String.valueOf(store.getId())).get(0).get("avg_price").toString());
+            } else {
+                store.setAvgPrice("0");
+            }
+
+            // 设置最新代金券(只显示一个)
+            if (latestCouponMap.containsKey(store.getId())) {
+                LifeCoupon latestCoupon = latestCouponMap.get(store.getId());
+                LifeCouponVo couponVo = new LifeCouponVo();
+                BeanUtils.copyProperties(latestCoupon, couponVo);
+                // 只设置一个代金券到列表中
+                List<LifeCouponVo> couponList = new ArrayList<>();
+                couponList.add(couponVo);
+                store.setCouponList(couponList);
+            } else {
+                // 如果没有代金券,设置为空列表
+                store.setCouponList(new ArrayList<>());
+            }
+        }
+
+        // 创建分页对象
+        IPage<StoreInfoVo> resultPage = new Page<>(pageNum, pageSize);
+        resultPage.setRecords(pagedList);
+        resultPage.setTotal(total);
+        resultPage.setCurrent(pageNum);
+        resultPage.setSize(pageSize);
+        resultPage.setPages((total + pageSize - 1) / pageSize);
+
+        return resultPage;
+    }
+
+    @Override
+    public List<StoreDictionary> getAllBusinessSection() {
+        // 查询所有经营种类数据
+        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");
+        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
+        queryWrapper.orderByAsc(StoreDictionary::getSortId);
+        List<StoreDictionary> storeDictionaryList = storeDictionaryMapper.selectList(queryWrapper);
+
+        // 构建三级树形结构
+        return buildTreeOptimized(storeDictionaryList);
+    }
+
+    @Override
+    public List<StoreDictionary> getAllBusinessSection(String businessSection) {
+        // 如果没有传入一级分类参数,返回所有分类
+        if (businessSection == null || businessSection.trim().isEmpty()) {
+            return getAllBusinessSection();
+        }
+
+        // 1. 根据dictId查询一级分类
+        StoreDictionary firstLevelDict = storeDictionaryMapper.selectOne(
+                new LambdaQueryWrapper<StoreDictionary>()
+                        .eq(StoreDictionary::getDictId, businessSection.trim())
+                        .eq(StoreDictionary::getTypeName, "business_section")
+                        .eq(StoreDictionary::getDeleteFlag, 0)
+        );
+
+        if (firstLevelDict == null) {
+            log.warn("未找到一级分类,businessSection={}", businessSection);
+            return new ArrayList<>();
+        }
+
+        // 2. 查询该一级分类下的所有二级分类(business_type)
+        List<StoreDictionary> secondLevelDicts = storeDictionaryMapper.selectList(
+                new LambdaQueryWrapper<StoreDictionary>()
+                        .eq(StoreDictionary::getTypeName, "business_type")
+                        .eq(StoreDictionary::getParentId, firstLevelDict.getId())
+                        .eq(StoreDictionary::getDeleteFlag, 0)
+                        .orderByAsc(StoreDictionary::getSortId)
+        );
+
+        if (secondLevelDicts.isEmpty()) {
+            // 如果没有二级分类,只返回一级分类
+            firstLevelDict.setStoreDictionaryList(new ArrayList<>());
+            return Collections.singletonList(firstLevelDict);
+        }
+
+        // 3. 获取所有二级分类的ID
+        List<Integer> secondLevelIds = secondLevelDicts.stream()
+                .map(StoreDictionary::getId)
+                .collect(Collectors.toList());
+
+        // 4. 查询这些二级分类下的所有三级分类(business_classify)
+        List<StoreDictionary> thirdLevelDicts = storeDictionaryMapper.selectList(
+                new LambdaQueryWrapper<StoreDictionary>()
+                        .eq(StoreDictionary::getTypeName, "business_classify")
+                        .in(StoreDictionary::getParentId, secondLevelIds)
+                        .eq(StoreDictionary::getDeleteFlag, 0)
+                        .orderByAsc(StoreDictionary::getSortId)
+        );
+
+        // 5. 构建树形结构
+        // 将一级分类、二级分类、三级分类合并
+        List<StoreDictionary> allDicts = new ArrayList<>();
+        allDicts.add(firstLevelDict);
+        allDicts.addAll(secondLevelDicts);
+        allDicts.addAll(thirdLevelDicts);
+
+        // 构建树形结构
+        return buildTreeOptimized(allDicts);
+    }
+
+
+
 }