| | |
| | | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.xiaopeng.api.model.operation.XpOpenCity; |
| | | import com.xiaopeng.api.model.operation.XpRegion; |
| | | import com.xiaopeng.common.core.constant.CacheConstants; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | | import com.xiaopeng.operation.mapper.XpRegionMapper; |
| | | import com.xiaopeng.api.model.operation.XpRegion; |
| | | import com.xiaopeng.operation.service.XpOpenCityService; |
| | | import com.xiaopeng.operation.service.XpRegionService; |
| | | import com.xiaopeng.operation.vo.RegionCascaderVO; |
| | | import com.xiaopeng.operation.vo.RegionDistrictSyncResultVO; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | |
| | | @Resource |
| | | private RedisService redisService; |
| | | @Resource |
| | | private XpOpenCityService openCityService; |
| | | |
| | | @Override |
| | | public List<List<XpRegion>> getXpRegion() { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<RegionCascaderVO> getRegionCascader() { |
| | | List<Object> cacheList = redisService.getCacheList(CacheConstants.XP_REGION_CASCADER); |
| | | if (cacheList != null && !cacheList.isEmpty()) { |
| | | try { |
| | | return cacheList.stream() |
| | | .filter(item -> item instanceof RegionCascaderVO) |
| | | .map(item -> (RegionCascaderVO) item) |
| | | .collect(Collectors.toList()); |
| | | } catch (ClassCastException e) { |
| | | redisService.deleteObject(CacheConstants.XP_REGION_CASCADER); |
| | | } |
| | | } |
| | | |
| | | List<XpRegion> regionList = this.baseMapper.selectList(Wrappers.lambdaQuery(XpRegion.class)); |
| | | if (regionList == null || regionList.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | List<XpOpenCity> openCityList = openCityService.list(Wrappers.lambdaQuery(XpOpenCity.class) |
| | | .eq(XpOpenCity::getStatus, 1)); |
| | | Set<String> openCityCodeSet = openCityList.stream() |
| | | .map(XpOpenCity::getCityCode) |
| | | .filter(StringUtils::isNotBlank) |
| | | .collect(Collectors.toCollection(HashSet::new)); |
| | | Set<String> openDistrictCodeSet = openCityList.stream() |
| | | .map(XpOpenCity::getDistrictCode) |
| | | .filter(StringUtils::isNotBlank) |
| | | .collect(Collectors.toCollection(HashSet::new)); |
| | | |
| | | Map<Long, List<XpRegion>> childrenMap = regionList.stream() |
| | | .collect(Collectors.groupingBy(region -> region.getParentId() == null ? 0L : region.getParentId())); |
| | | List<XpRegion> provinceList = childrenMap.getOrDefault(0L, Collections.emptyList()).stream() |
| | | .sorted(REGION_COMPARATOR) |
| | | .collect(Collectors.toList()); |
| | | List<RegionCascaderVO> result = provinceList.stream() |
| | | .map(region -> buildRegionNode(region, childrenMap, openCityCodeSet, openDistrictCodeSet)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | redisService.setCacheList(CacheConstants.XP_REGION_CASCADER, result); |
| | | return result; |
| | | } |
| | | |
| | | private RegionCascaderVO buildRegionNode(XpRegion current, |
| | | Map<Long, List<XpRegion>> childrenMap, |
| | | Set<String> openCityCodeSet, |
| | | Set<String> openDistrictCodeSet) { |
| | | List<XpRegion> children = childrenMap.getOrDefault(current.getId(), Collections.emptyList()).stream() |
| | | .sorted(REGION_COMPARATOR) |
| | | .collect(Collectors.toList()); |
| | | List<RegionCascaderVO> childNodes = children.stream() |
| | | .map(child -> buildRegionNode(child, childrenMap, openCityCodeSet, openDistrictCodeSet)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | Integer level = resolveRegionLevel(current.getCode()); |
| | | Integer selfOpen = resolveSelfOpen(level, current.getCode(), openCityCodeSet, openDistrictCodeSet); |
| | | boolean hasOpenChild = childNodes.stream().anyMatch(node -> Integer.valueOf(1).equals(node.getIsOpen())); |
| | | |
| | | RegionCascaderVO node = new RegionCascaderVO(); |
| | | node.setCode(current.getCode()); |
| | | node.setName(current.getName()); |
| | | node.setLeaf(Integer.valueOf(3).equals(level)); |
| | | node.setChildren(childNodes); |
| | | node.setIsOpen(selfOpen == 1 || hasOpenChild ? 1 : 0); |
| | | return node; |
| | | } |
| | | |
| | | private Integer resolveRegionLevel(String code) { |
| | | if (StringUtils.isBlank(code) || code.length() < 4) { |
| | | return 3; |
| | | } |
| | | if (code.endsWith("0000")) { |
| | | return 1; |
| | | } |
| | | if (code.endsWith("00")) { |
| | | return 2; |
| | | } |
| | | return 3; |
| | | } |
| | | |
| | | private Integer resolveSelfOpen(Integer level, |
| | | String code, |
| | | Set<String> openCityCodeSet, |
| | | Set<String> openDistrictCodeSet) { |
| | | if (StringUtils.isBlank(code)) { |
| | | return 0; |
| | | } |
| | | if (Integer.valueOf(2).equals(level)) { |
| | | return openCityCodeSet.contains(code) ? 1 : 0; |
| | | } |
| | | if (Integer.valueOf(3).equals(level)) { |
| | | return openDistrictCodeSet.contains(code) ? 1 : 0; |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | private static final Comparator<XpRegion> REGION_COMPARATOR = Comparator |
| | | .comparing((XpRegion region) -> StringUtils.defaultString(region.getInitial())) |
| | | .thenComparing((XpRegion region) -> StringUtils.defaultString(region.getCode())); |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public RegionDistrictSyncResultVO syncDistrictFromRegionAll() { |
| | | Long cityCount = Objects.requireNonNullElse(this.baseMapper.countCityForDistrictSync(), 0L); |
| | | Long candidateDistrictCount = Objects.requireNonNullElse(this.baseMapper.countCandidateDistrictForSync(), 0L); |
| | | Long cityCount = this.baseMapper.countCityForDistrictSync(); |
| | | if (cityCount == null) { |
| | | cityCount = 0L; |
| | | } |
| | | Long candidateDistrictCount = this.baseMapper.countCandidateDistrictForSync(); |
| | | if (candidateDistrictCount == null) { |
| | | candidateDistrictCount = 0L; |
| | | } |
| | | |
| | | List<XpRegion> missingDistrictList = this.baseMapper.selectMissingDistrictFromRegionAll(); |
| | | long insertedCount = 0L; |
| | |
| | | |
| | | redisService.deleteObject(CacheConstants.XP_REGION); |
| | | redisService.deleteObject(CacheConstants.XP_REGION_CITY); |
| | | redisService.deleteObject(CacheConstants.XP_REGION_CASCADER); |
| | | |
| | | RegionDistrictSyncResultVO result = new RegionDistrictSyncResultVO(); |
| | | result.setCityCount(cityCount); |