| | |
| | | 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.StoreCustomerDetailDto; |
| | | import com.oying.modules.pc.store.domain.dto.StoreCustomerQueryCriteria; |
| | | 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.beans.BeanUtils; |
| | | 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<Object, Object> redisTemplate; |
| | | private final StoreService storeService; |
| | | |
| | | @Override |
| | | public StoreCustomerDetailDto getCustomerStoreDetail(StoreCustomerQueryCriteria criteria) { |
| | | Store store = storeService.getById(criteria.getStoreId()); |
| | | StoreCustomerDetailDto storeDto = new StoreCustomerDetailDto(); |
| | | BeanUtils.copyProperties(store, storeDto); |
| | | storeDto.setName(store.getStoreName()); |
| | | storeDto.setLogoUrl(""); |
| | | storeDto.setBusinessHours(""); |
| | | storeDto.setDeliveryDuration(0); |
| | | storeDto.setMonthlySales(0); |
| | | storeDto.setScore(0); |
| | | return storeDto; |
| | | public PageResult<Store> findPagedStores(StoreQueryCriteria criteria) { |
| | | |
| | | PageResult<Store> page = new PageResult<>(); |
| | | |
| | | // 1. 检查ZSET是否存在 |
| | | String setKey = criteria.buildConditionCacheKey(); |
| | | Long total = redisTemplate.opsForZSet().size(setKey); |
| | | if (total == null || total == 0) { |
| | | // 初始化缓存 |
| | | List<Long> 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<Long> storeIds = Optional.ofNullable(redisTemplate.opsForZSet().range(setKey, offset, end)) |
| | | .orElse(Collections.emptySet()) |
| | | .stream() |
| | | .map(i -> (Long) i) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | // 3. 获取详情数据] |
| | | List<Store> 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(); |
| | | } |
| | | } |