|
|
@@ -4834,6 +4834,181 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
// SQL已经实现了距离过滤和排序,直接返回结果
|
|
|
return storeInfoVoList;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据店铺ID获取推荐店铺列表(用户端)
|
|
|
+ * <p>
|
|
|
+ * 只使用store_id查询,不包含其他筛选条件(经营板块、经营分类、分类、经纬度等)
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param storeId 店铺ID,必填,必须大于0
|
|
|
+ * @return 推荐店铺列表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<StoreInfoVo> getRecommendedStoresByStoreId(Integer storeId) {
|
|
|
+ log.info("根据店铺ID获取推荐店铺列表,storeId={}", storeId);
|
|
|
+
|
|
|
+ // 参数校验
|
|
|
+ if (storeId == null || storeId <= 0) {
|
|
|
+ log.warn("获取推荐店铺列表失败,店铺ID无效:{}", storeId);
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ 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); // 过滤禁用的店铺
|
|
|
+
|
|
|
+ // 排除当前店铺
|
|
|
+ queryWrapper.ne("a.id", storeId);
|
|
|
+
|
|
|
+ // 过期时间判断
|
|
|
+ Date currentDate = new Date();
|
|
|
+ // 如果 expiration_time 为空则不做过期判断;如果不为空则要求大于当前时间
|
|
|
+ queryWrapper.and(w -> w.isNull("a.expiration_time")
|
|
|
+ .or()
|
|
|
+ .gt("a.expiration_time", currentDate));
|
|
|
+
|
|
|
+ // 如果 food_licence_expiration_time 为空则不做过期判断;如果不为空则要求大于当前时间
|
|
|
+ queryWrapper.and(w -> w.isNull("a.food_licence_expiration_time")
|
|
|
+ .or()
|
|
|
+ .gt("a.food_licence_expiration_time", currentDate));
|
|
|
+
|
|
|
+ // 查询店铺列表(限制20条)
|
|
|
+ queryWrapper.last("limit 20");
|
|
|
+
|
|
|
+ List<StoreInfoVo> 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<>();
|
|
|
+
|
|
|
+ // 注意:需要将store_id转换为String类型,与后续containsKey判断保持一致
|
|
|
+ avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
|
|
|
+ .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
|
|
|
+ List<StoreComment> storeComments = storeCommentMapper.selectList(
|
|
|
+ new QueryWrapper<StoreComment>()
|
|
|
+ .eq("business_type", "5")
|
|
|
+ .eq("delete_flag", 0));
|
|
|
+ commentMap = storeComments.stream()
|
|
|
+ .filter(comment -> comment.getStoreId() != null)
|
|
|
+ .collect(Collectors.groupingBy(StoreComment::getStoreId));
|
|
|
+
|
|
|
+ // 查询入口头图
|
|
|
+ List<Integer> storeIds = storeInfoVoList.stream()
|
|
|
+ .map(StoreInfoVo::getId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<StoreImg> storeImgList = storeImgMapper.selectList(
|
|
|
+ new QueryWrapper<StoreImg>()
|
|
|
+ .in("store_id", storeIds)
|
|
|
+ .eq("img_type", 1));
|
|
|
+ Map<Integer, List<StoreImg>> storeCollect = storeImgList.stream()
|
|
|
+ .collect(Collectors.groupingBy(StoreImg::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 (!CollectionUtils.isEmpty(storeCollect) && storeCollect.containsKey(record.getId())) {
|
|
|
+ List<StoreImg> storeImgs = storeCollect.get(record.getId());
|
|
|
+ if (!CollectionUtils.isEmpty(storeImgs)) {
|
|
|
+ record.setEntranceImage(storeImgs.get(0).getImgUrl());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理经纬度
|
|
|
+ if (StringUtils.isNotEmpty(record.getStorePosition())) {
|
|
|
+ String[] split = record.getStorePosition().split(",");
|
|
|
+ if (split.length >= 2) {
|
|
|
+ record.setStorePositionLongitude(split[0]);
|
|
|
+ record.setStorePositionLatitude(split[1]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理到期状态
|
|
|
+ Date expirationTime = record.getExpirationTime();
|
|
|
+ if (expirationTime != null) {
|
|
|
+ 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 (!CollectionUtils.isEmpty(avgScoreMap) && avgScoreMap.containsKey(String.valueOf(record.getId()))) {
|
|
|
+ record.setAvgScore(String.valueOf(avgScoreMap.get(String.valueOf(record.getId())).get(0).get("avg_score")));
|
|
|
+ } else {
|
|
|
+ record.setAvgScore("0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置总评论数
|
|
|
+ if (!CollectionUtils.isEmpty(commentMap) && commentMap.containsKey(record.getId())) {
|
|
|
+ record.setTotalNum(String.valueOf(commentMap.get(record.getId()).size()));
|
|
|
+ } else {
|
|
|
+ record.setTotalNum("0");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("根据店铺ID获取推荐店铺列表成功,storeId={},返回店铺数量:{}", storeId, storeInfoVoList.size());
|
|
|
+ return storeInfoVoList;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("根据店铺ID获取推荐店铺列表异常,storeId={},异常信息:{}", storeId, e.getMessage(), e);
|
|
|
+ throw new RuntimeException("获取推荐店铺列表失败:" + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public int uploadEntertainmentLicence(StoreImg storeImg) {
|
|
|
storeImgMapper.delete(new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 24).eq(StoreImg::getStoreId, storeImg.getStoreId()));
|