|
|
@@ -2680,7 +2680,7 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
// 过滤永久关门的店铺
|
|
|
queryWrapper.ne("a.business_status", 99);
|
|
|
// 过滤过期的经营许可证
|
|
|
- queryWrapper.ge("a.food_licence_expiration_time", new Date());
|
|
|
+ queryWrapper.ge("a.entertainment_licence_expiration_time", new Date());
|
|
|
|
|
|
// 距离优先模式:只显示10公里内且3.5星以上的店铺
|
|
|
final Double finalDistance;
|
|
|
@@ -4140,4 +4140,439 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
throw new RuntimeException("调用门店审核接口异常", e);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ @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;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|