package com.oying.modules.pc.store.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; import com.oying.modules.pc.store.domain.Store; import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria; import com.oying.modules.pc.store.service.StoreQueryService; import com.oying.modules.pc.store.service.StoreService; import com.oying.utils.PageResult; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Slf4j @Service @RequiredArgsConstructor public class StoreQueryServiceImpl implements StoreQueryService { private final RedisTemplate redisTemplate; private final StoreService storeService; @Override public PageResult findPagedStores(StoreQueryCriteria criteria) { PageResult page = new PageResult<>(); // 1. 检查ZSET是否存在 String setKey = criteria.buildConditionCacheKey(); Long total = redisTemplate.opsForZSet().size(setKey); if (total == null || total == 0) { // 初始化缓存 List ids = storeService.queryStoreIds(criteria); int index = 0; for (Long id : ids) { redisTemplate.opsForZSet().add(setKey, id, index++); } // 设置缓存过期时间 redisTemplate.expire(setKey, 15, TimeUnit.MINUTES); total = (long) ids.size(); } // 2. 从ZSET获取分页ID int current = (criteria.getPage() == null || criteria.getPage() < 1) ? 1 : criteria.getPage(); int offset = (current - 1) * criteria.getSize(); int end = offset + criteria.getSize() - 1; Set storeIds = Optional.ofNullable(redisTemplate.opsForZSet().range(setKey, offset, end)) .orElse(Collections.emptySet()) .stream() .map(i -> (Long) i) .collect(Collectors.toSet()); // 3. 获取详情数据] List stores = Optional.of(storeIds) .filter(CollectionUtil::isNotEmpty) .map(storeService::getStoresByIds) .orElse(ListUtil.toList()); stores.forEach(u -> u.setDeliveryDuration(distanceCalculation(criteria.getLatitude(), criteria.getLongitude(), u.getLatitude(), u.getLongitude()))); page.setContent(stores); page.setTotalElements(total); return page; } private Integer distanceCalculation(double lat1, double lon1, double lat2, double lon2) { // 地球半径(千米) final int R = 6371; // 将纬度、经度从度转换为弧度 double latDistance = Math.toRadians(lat2 - lat1); double lonDistance = Math.toRadians(lon2 - lon1); double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return new Double(R * c * 1000).intValue(); } }