@@ -0,0 +1,43 @@ | |||
package com.ningdatech.pmapi.common.constant; | |||
/** | |||
* <p> | |||
* RegionConst | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 13:57 2023/3/1 | |||
*/ | |||
public interface RegionConst { | |||
//---------------------------------------地区层级(缩写RL)------------------------------------------------------------- | |||
int RL_PROVINCE = 1; | |||
int RL_CITY = 2; | |||
int RL_COUNTY = 3; | |||
//---------------------------------------地区编码(缩写RC)------------------------------------------------------------- | |||
/** | |||
* 丽水行政区划编码 | |||
*/ | |||
String RC_LS = "331100"; | |||
/** | |||
* 中国行政区划编码 | |||
*/ | |||
String RC_CHINA = "100000"; | |||
/** | |||
* 浙江行政区划编码 | |||
*/ | |||
String RC_ZJ = "330000"; | |||
//----------------------------------------地区父级ID(缩写PID)--------------------------------------------------------- | |||
long PID_CHINA = 0; | |||
} |
@@ -1,19 +0,0 @@ | |||
package com.ningdatech.pmapi.common.constant; | |||
/** | |||
* <p> | |||
* RegionLevelConst | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 13:57 2023/3/1 | |||
*/ | |||
public interface RegionLevelConst { | |||
int PROVINCE = 1; | |||
int CITY = 2; | |||
int COUNTY = 3; | |||
} |
@@ -2,10 +2,10 @@ package com.ningdatech.pmapi.common.helper; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionTreeDTO; | |||
import com.ningdatech.pmapi.sys.model.vo.RegionTreeVO; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* <p> | |||
@@ -23,52 +23,14 @@ public interface RegionCacheHelper { | |||
* | |||
* @return / | |||
*/ | |||
List<RegionTreeDTO> all(); | |||
/** | |||
* 获取用于前端回显示使用的unionList 仅用于返回前端的时候使用 | |||
* | |||
* @param code 区域编码 | |||
* @param level 区域层级 | |||
* @return | |||
*/ | |||
String getUnionPathStr(String code, Integer level); | |||
/** | |||
* 原专家库数据导入使用 返回名称区域Map | |||
* | |||
* @return | |||
*/ | |||
Map<String, RegionDTO> getNameRegionMap(); | |||
/** | |||
* key.getRegionCode() + "###" + key.getRegionLevel() ,regionMap.get(key) | |||
* | |||
* @return | |||
*/ | |||
Map<String, RegionDTO> getRegionMap(); | |||
/** | |||
* 获取市级区域列表 | |||
* | |||
* @return | |||
*/ | |||
List<RegionDTO> getMunicipalRegion(); | |||
/** | |||
* 获取省级区域列表 | |||
* | |||
* @return / | |||
*/ | |||
List<RegionDTO> getProvincialRegion(); | |||
List<RegionDTO> all(); | |||
/** | |||
* 根据区域code 区域层级获取 区域类 | |||
* | |||
* @param code 区域编码 | |||
* @param level 区域层级 | |||
* @return / | |||
* @return {@link RegionDTO} | |||
*/ | |||
RegionDTO getByCodeAndLevel(String code, int level); | |||
@@ -83,29 +45,39 @@ public interface RegionCacheHelper { | |||
List<RegionDTO> listParents(String code, int level); | |||
/** | |||
* 获取所有区域编码「parent -> child」 | |||
* 获取当前区域所有的子区域(包括自己) | |||
* | |||
* @param regionCode 区域编码 | |||
* @param regionLevel 级别 | |||
* @param code 区域编码 | |||
* @param level 级别 | |||
* @return / | |||
*/ | |||
List<String> getRegionCodes(String regionCode, int regionLevel); | |||
Collection<String> listChildRegionCodeList(String code, int level); | |||
/** | |||
* 获取当前区域所有的子集 | |||
* 获取当前节点开始的区域树 | |||
* | |||
* @param code 区域编码 | |||
* @param level 级别 | |||
* @return / | |||
* @param regionCode 区域编码 | |||
* @param regionLevel 区域层级 | |||
* @return 区域树 | |||
*/ | |||
List<String> getAllChildrenRegionCodeList(String code, int level); | |||
RegionTreeVO getRegionTree(String regionCode, Integer regionLevel); | |||
/** | |||
* 获取展示名称(浙江省/杭州市/滨江区) | |||
* | |||
* @param regionCode 区域编码 | |||
* @param regionLevel 区域层级 | |||
* @return java.lang.String | |||
**/ | |||
String getFullDisplayName(String regionCode, Integer regionLevel); | |||
/** | |||
* 获取 根节点 区域层级编码 | |||
* 获取展示名称(杭州市/滨江区) | |||
* | |||
* @return / | |||
*/ | |||
String getParentCodeRoot(); | |||
* @param regionCode 区域编码 | |||
* @param regionLevel 区域层级 | |||
* @return java.lang.String | |||
**/ | |||
String getDisplayName(String regionCode, Integer regionLevel); | |||
} |
@@ -1,138 +0,0 @@ | |||
package com.ningdatech.pmapi.common.helper.basic; | |||
import com.github.benmanes.caffeine.cache.Caffeine; | |||
import com.github.benmanes.caffeine.cache.LoadingCache; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.pmapi.common.helper.RegionCacheHelper; | |||
import com.ningdatech.pmapi.common.model.RegionMapKey; | |||
import com.ningdatech.pmapi.sys.convert.RegionConverter; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionTreeDTO; | |||
import com.ningdatech.pmapi.sys.service.IRegionService; | |||
import org.apache.commons.collections4.CollectionUtils; | |||
import org.springframework.beans.factory.InitializingBean; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import java.util.*; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
import java.util.concurrent.TimeUnit; | |||
import java.util.stream.Collectors; | |||
/** | |||
* <p> | |||
* AbstractRegionCache | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 14:41 2023/3/1 | |||
*/ | |||
public abstract class AbstractRegionCache implements InitializingBean, RegionCacheHelper { | |||
@Autowired | |||
private IRegionService regionService; | |||
/** | |||
* 当前支持最大层级 | |||
*/ | |||
private static final int REGION_LEVEL_MAX = 3; | |||
private LoadingCache<String, List<RegionTreeDTO>> regionsCache; | |||
/** | |||
* 中国行政区划编码 | |||
*/ | |||
private static final String PARENT_CODE_ROOT = "100000"; | |||
protected Map<RegionMapKey, RegionDTO> regionMap; | |||
@Override | |||
public void afterPropertiesSet() { | |||
regionsCache = Caffeine.newBuilder() | |||
.expireAfterWrite(10, TimeUnit.MINUTES) | |||
.refreshAfterWrite(5, TimeUnit.MINUTES) | |||
.build(key -> { | |||
// 查询全部 | |||
List<RegionDTO> regionDTOList = regionService.all(); | |||
if (regionDTOList.isEmpty()) { | |||
throw BizException.wrap("区域元数据不能为空"); | |||
} | |||
regionMap = buildCacheMap(regionDTOList); | |||
List<RegionDTO> regionInLevel = regionMap.values().stream() | |||
.filter(regionDTO -> { | |||
// 只过滤出小于等于level的region | |||
if (Objects.isNull(regionDTO.getRegionLevel())) { | |||
return false; | |||
} | |||
return Integer.parseInt(key) >= regionDTO.getRegionLevel(); | |||
}).collect(Collectors.toList()); | |||
List<RegionTreeDTO> treeDtos = RegionConverter.toRegionTreeDTOList(regionInLevel); | |||
return toTreeStructure(treeDtos); | |||
}); | |||
warmUp(); | |||
} | |||
protected List<RegionTreeDTO> getByLevel(int level) { | |||
return regionsCache.get(String.valueOf(level)); | |||
} | |||
private Map<RegionMapKey, RegionDTO> buildCacheMap(List<RegionDTO> regionDTOList) { | |||
Map<RegionMapKey, RegionDTO> regionDtoMap = new ConcurrentHashMap<>(256); | |||
regionDTOList.forEach(region -> { | |||
RegionMapKey key = RegionMapKey.builder() | |||
.regionCode(region.getRegionCode()) | |||
.regionLevel(region.getRegionLevel()) | |||
.build(); | |||
regionDtoMap.put(key, region); | |||
}); | |||
return regionDtoMap; | |||
} | |||
private List<RegionTreeDTO> toTreeStructure(List<RegionTreeDTO> rootList) { | |||
List<RegionTreeDTO> nodeList = new ArrayList<>(); | |||
for (RegionTreeDTO treeNode : rootList) { | |||
if (PARENT_CODE_ROOT.equals(treeNode.getParentCode()) || Objects.isNull(treeNode.getParentCode())) { | |||
nodeList.add(treeNode); | |||
} | |||
treeNode.setChildren(getChildren(treeNode.getRegionCode(), treeNode.getLevel(), rootList)); | |||
} | |||
return nodeList; | |||
} | |||
private List<RegionTreeDTO> getChildren(String regionCode, int regionLevel, List<RegionTreeDTO> list) { | |||
List<RegionTreeDTO> childList = new ArrayList<>(); | |||
for (RegionTreeDTO regionTreeDTO : list) { | |||
if (regionCode.equals(regionTreeDTO.getParentCode()) && regionLevel + 1 == regionTreeDTO.getLevel()) { | |||
childList.add(regionTreeDTO); | |||
} | |||
} | |||
for (RegionTreeDTO regionTreeDTO : childList) { | |||
regionTreeDTO.setChildren(getChildren(regionTreeDTO.getRegionCode(), regionTreeDTO.getLevel(), list)); | |||
} | |||
if (CollectionUtils.isEmpty(childList)) { | |||
return Collections.emptyList(); | |||
} | |||
childList.sort(Comparator.comparing(RegionTreeDTO::getRegionCode)); | |||
return childList; | |||
} | |||
private void warmUp() { | |||
for (int level = 1; level <= REGION_LEVEL_MAX; level++) { | |||
getByLevel(level); | |||
} | |||
} | |||
protected List<RegionTreeDTO> getCopyListByLevel(int level) { | |||
List<RegionTreeDTO> regionTreeDtos = regionsCache.get(String.valueOf(level)); | |||
List<RegionTreeDTO> copyRegionTreeDtos = new ArrayList<>(); | |||
if (CollectionUtils.isNotEmpty(regionTreeDtos)) { | |||
copyRegionTreeDtos.addAll(regionTreeDtos); | |||
} | |||
return copyRegionTreeDtos; | |||
} | |||
@Override | |||
public String getParentCodeRoot() { | |||
return PARENT_CODE_ROOT; | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
package com.ningdatech.pmapi.common.helper.basic; | |||
import cn.hutool.core.lang.Assert; | |||
import com.github.benmanes.caffeine.cache.Caffeine; | |||
import com.github.benmanes.caffeine.cache.LoadingCache; | |||
import com.ningdatech.pmapi.common.model.RegionMapKey; | |||
import com.ningdatech.pmapi.sys.convert.RegionConverter; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import com.ningdatech.pmapi.sys.service.IRegionService; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.assertj.core.util.Lists; | |||
import org.springframework.beans.factory.InitializingBean; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import java.util.List; | |||
import java.util.concurrent.TimeUnit; | |||
/** | |||
* <p> | |||
* AbstractRegionCache | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 14:41 2023/3/1 | |||
*/ | |||
@Slf4j | |||
public abstract class AbstractRegionCacheHelper implements InitializingBean { | |||
@Autowired | |||
private IRegionService regionService; | |||
private LoadingCache<RegionMapKey, RegionDTO> regionsCache; | |||
private void initRegionCache() { | |||
List<RegionDTO> allRegions = regionService.all(); | |||
if (allRegions.isEmpty()) { | |||
log.warn("区域元数据未初始化"); | |||
return; | |||
} | |||
allRegions.forEach(w -> { | |||
RegionMapKey key = RegionMapKey.of(w.getRegionCode(), w.getRegionLevel()); | |||
regionsCache.put(key, w); | |||
}); | |||
} | |||
protected RegionDTO get(RegionMapKey key) { | |||
return regionsCache.get(key); | |||
} | |||
protected List<RegionDTO> all() { | |||
return Lists.newArrayList(regionsCache.asMap().values()); | |||
} | |||
@Override | |||
public void afterPropertiesSet() { | |||
regionsCache = Caffeine.newBuilder() | |||
.refreshAfterWrite(7, TimeUnit.DAYS) | |||
.maximumSize(512) | |||
.build(key -> { | |||
Region region = regionService.getOne(key.getRegionCode(), key.getRegionLevel()); | |||
Assert.notNull(region, "区域不存在:%s", key); | |||
return RegionConverter.toRegionDTO(region); | |||
}); | |||
// 初始化所有区域数据到缓存 | |||
initRegionCache(); | |||
} | |||
} |
@@ -20,7 +20,7 @@ import java.util.Objects; | |||
@AllArgsConstructor | |||
public abstract class AbstractRegionLimitHelper implements RegionLimitHelper { | |||
protected final RegionCacheHelper regionCacheHelper; | |||
protected final RegionCacheHelper regionCache; | |||
protected final IExpertUserFullInfoService expertUserFullInfoService; | |||
@@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory; | |||
import org.springframework.stereotype.Component; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
@@ -24,8 +25,8 @@ public class RegionLimitHelperImpl extends AbstractRegionLimitHelper { | |||
private static final Logger logger = LoggerFactory.getLogger(RegionLimitHelperImpl.class); | |||
public RegionLimitHelperImpl(RegionCacheHelper regionCacheHelper, IExpertUserFullInfoService expertUserFullInfoService) { | |||
super(regionCacheHelper, expertUserFullInfoService); | |||
public RegionLimitHelperImpl(RegionCacheHelper regionCache, IExpertUserFullInfoService expertUserFullInfoService) { | |||
super(regionCache, expertUserFullInfoService); | |||
} | |||
public static Boolean contains(Integer adminRegionLevel, List<String> adminAllContainsRegionCodes | |||
@@ -88,12 +89,11 @@ public class RegionLimitHelperImpl extends AbstractRegionLimitHelper { | |||
@Override | |||
public RegionContainsBO getContainsRegionBo(Integer regionLevel, String regionCode) { | |||
List<String> regionCodes = regionCacheHelper | |||
.getAllChildrenRegionCodeList(regionCode, regionLevel); | |||
RegionContainsBO regionContainsBO = new RegionContainsBO(); | |||
regionContainsBO.setContainsRegionCodeList(regionCodes); | |||
regionContainsBO.setParentRegionTreeLevel(regionLevel); | |||
return regionContainsBO; | |||
Collection<String> regionCodes = regionCache.listChildRegionCodeList(regionCode, regionLevel); | |||
RegionContainsBO regionContains = new RegionContainsBO(); | |||
regionContains.setContainsRegionCodeList(new ArrayList<>(regionCodes)); | |||
regionContains.setParentRegionTreeLevel(regionLevel); | |||
return regionContains; | |||
} | |||
@Override | |||
@@ -0,0 +1,167 @@ | |||
package com.ningdatech.pmapi.common.helper.impl; | |||
import cn.hutool.core.text.StrPool; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.pmapi.common.constant.RegionConst; | |||
import com.ningdatech.pmapi.common.helper.RegionCacheHelper; | |||
import com.ningdatech.pmapi.common.helper.basic.AbstractRegionCacheHelper; | |||
import com.ningdatech.pmapi.common.model.RegionMapKey; | |||
import com.ningdatech.pmapi.common.util.StrUtils; | |||
import com.ningdatech.pmapi.sys.convert.RegionConverter; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionTreeDTO; | |||
import com.ningdatech.pmapi.sys.model.vo.RegionTreeVO; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.collections4.CollectionUtils; | |||
import org.springframework.stereotype.Component; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @author liuxinxin | |||
* @date 2022/7/22 上午8:58 | |||
* 构建地区码 地区树 | |||
*/ | |||
@Slf4j | |||
@Component | |||
public class RegionsCacheHelperImpl extends AbstractRegionCacheHelper implements RegionCacheHelper { | |||
@Override | |||
public RegionDTO getByCodeAndLevel(String code, int level) { | |||
return super.get(RegionMapKey.of(code, level)); | |||
} | |||
@Override | |||
public List<RegionDTO> all() { | |||
return super.all(); | |||
} | |||
@Override | |||
public Collection<String> listChildRegionCodeList(String regionCode, int regionLevel) { | |||
RegionDTO currRegion = getByCodeAndLevel(regionCode, regionLevel); | |||
if (currRegion.getParentCode().equals(regionCode)) { | |||
return Collections.singletonList(regionCode); | |||
} | |||
List<RegionDTO> allRegions = all(); | |||
return allRegions.stream().filter(w -> StrUtils.split(w.getRegionCodePath()).contains(regionCode)) | |||
.map(RegionDTO::getRegionCode).collect(Collectors.toSet()); | |||
} | |||
@Override | |||
public RegionTreeVO getRegionTree(String regionCode, Integer regionLevel) { | |||
Map<Long, List<RegionDTO>> regions; | |||
Long parentId; | |||
if (regionCode == null || regionCode.equals(RegionConst.RC_CHINA)) { | |||
regions = CollUtils.group(all(), RegionDTO::getParentId); | |||
parentId = RegionConst.PID_CHINA; | |||
} else { | |||
RegionDTO currRegion = getByCodeAndLevel(regionCode, regionLevel); | |||
if (currRegion.getParentCode().equals(regionCode)) { | |||
return RegionConverter.toRegionTreeVO(currRegion); | |||
} | |||
regions = all().stream() | |||
.filter(w -> StrUtils.split(w.getRegionCodePath()).contains(regionCode)) | |||
.collect(Collectors.groupingBy(RegionDTO::getParentId)); | |||
parentId = currRegion.getParentId(); | |||
} | |||
regions.values().forEach(w -> w.sort(Comparator.comparing(x -> Long.parseLong(x.getRegionCode())))); | |||
return RegionConverter.toRegionTree(parentId, regions, false).get(0); | |||
} | |||
@Override | |||
public String getFullDisplayName(String regionCode, Integer regionLevel) { | |||
RegionDTO regionCurr = getByCodeAndLevel(regionCode, regionLevel); | |||
return getDisplayName(regionCurr, RegionConst.RL_PROVINCE); | |||
} | |||
@Override | |||
public String getDisplayName(String regionCode, Integer regionLevel) { | |||
RegionDTO regionCurr = getByCodeAndLevel(regionCode, regionLevel); | |||
return getDisplayName(regionCurr, RegionConst.RL_CITY); | |||
} | |||
//------------------------------------------------------------------------------------------------------------------ | |||
/** | |||
* 获取指定层级的展示名称 | |||
* | |||
* @param region 当前区域 | |||
* @param sLevel 开始层级 | |||
* @return 展示名称 | |||
*/ | |||
private String getDisplayName(RegionDTO region, int sLevel) { | |||
Integer level = region.getRegionLevel(); | |||
if (RegionConst.RL_PROVINCE > sLevel || sLevel > level) { | |||
throw BizException.wrap("区域层级无效"); | |||
} | |||
if (sLevel == level) { | |||
return region.getRegionName(); | |||
} | |||
StringBuilder builder = new StringBuilder(); | |||
List<String> regionCodes = StrUtils.split(region.getRegionCodePath()); | |||
for (int i = regionCodes.size() - 1; i > 0; i--) { | |||
if (level <= sLevel) { | |||
break; | |||
} | |||
RegionDTO tmp = getByCodeAndLevel(regionCodes.get(i), --level); | |||
builder.append(tmp.getRegionName()).append(StrPool.SLASH); | |||
} | |||
builder.append(region.getRegionName()); | |||
return builder.toString(); | |||
} | |||
protected List<RegionTreeDTO> getCopyListByLevel(int level) { | |||
List<RegionDTO> regions = all().stream() | |||
.filter(w -> w.getRegionLevel() <= level) | |||
.collect(Collectors.toList()); | |||
return RegionConverter.toRegionTreeDTOList(regions); | |||
} | |||
/** | |||
* 获取某一个地区开始的层级树 | |||
* | |||
* @param list 地区集合 | |||
* @param code 地区编码 | |||
* @param level 地区层级 | |||
* @return / | |||
*/ | |||
private RegionTreeDTO getTreeByRegionAndCode(List<RegionTreeDTO> list, String code, int level) { | |||
if (CollectionUtils.isEmpty(list)) { | |||
list = getCopyListByLevel(3); | |||
if (CollectionUtils.isEmpty(list)) { | |||
return null; | |||
} | |||
} | |||
Optional<RegionTreeDTO> first = list.stream() | |||
.filter(w -> w.getRegionCode().equals(code) && w.getLevel() == level) | |||
.findFirst(); | |||
if (first.isPresent()) { | |||
return first.get(); | |||
} | |||
for (RegionTreeDTO dto : list) { | |||
if (CollectionUtils.isEmpty(dto.getChildren())) { | |||
continue; | |||
} | |||
RegionTreeDTO temp = getTreeByRegionAndCode(dto.getChildren(), code, level); | |||
if (temp != null) { | |||
return temp; | |||
} | |||
} | |||
return null; | |||
} | |||
@Override | |||
public List<RegionDTO> listParents(String code, int level) { | |||
List<RegionDTO> result = new ArrayList<>(); | |||
RegionDTO dto = getByCodeAndLevel(code, level); | |||
result.add(0, dto); | |||
if (RegionConst.RC_CHINA.equals(dto.getParentCode())) { | |||
return result; | |||
} | |||
result.addAll(0, listParents(dto.getParentCode(), dto.getRegionLevel() - 1)); | |||
return result; | |||
} | |||
} |
@@ -1,205 +0,0 @@ | |||
package com.ningdatech.pmapi.common.helper.impl; | |||
import cn.hutool.core.lang.Assert; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.pmapi.common.helper.basic.AbstractRegionCache; | |||
import com.ningdatech.pmapi.common.model.RegionMapKey; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionTreeDTO; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.collections4.CollectionUtils; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.springframework.stereotype.Component; | |||
import java.util.*; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
/** | |||
* @author liuxinxin | |||
* @date 2022/7/22 上午8:58 | |||
* 构建地区码 地区树 | |||
*/ | |||
@Slf4j | |||
@Component | |||
public class RegionsCacheImpl extends AbstractRegionCache { | |||
@Override | |||
public List<RegionTreeDTO> all() { | |||
return getByLevel(3); | |||
} | |||
@Override | |||
public List<String> getAllChildrenRegionCodeList(String code, int level) { | |||
List<RegionTreeDTO> regionTreeDTOList = all(); | |||
Set<String> childrenRegionCodeSet = new HashSet<>(); | |||
childrenRegionCodeSet.add(code); | |||
RegionTreeDTO currentRegionTree = getCurrentRegionTree(code, level, regionTreeDTOList); | |||
if (Objects.isNull(currentRegionTree)) { | |||
List<String> childrenRegionCodeList = new ArrayList<>(); | |||
childrenRegionCodeList.add(code); | |||
return childrenRegionCodeList; | |||
} | |||
getAllChildrenRegionCodeList(currentRegionTree.getChildren(), childrenRegionCodeSet); | |||
return new ArrayList<>(childrenRegionCodeSet); | |||
} | |||
private RegionTreeDTO getCurrentRegionTree(String code, int level, List<RegionTreeDTO> regionTreeDtos) { | |||
for (RegionTreeDTO regionTreeDTO : regionTreeDtos) { | |||
if (level == regionTreeDTO.getLevel() && code.equals(regionTreeDTO.getRegionCode())) { | |||
return regionTreeDTO; | |||
} | |||
if (CollectionUtils.isNotEmpty(regionTreeDTO.getChildren())) { | |||
return getCurrentRegionTree(code, level, regionTreeDTO.getChildren()); | |||
} | |||
} | |||
return null; | |||
} | |||
private void getAllChildrenRegionCodeList(List<RegionTreeDTO> regionTreeDtos, Set<String> childrenRegionCodeSet) { | |||
if (CollectionUtils.isEmpty(regionTreeDtos)) { | |||
return; | |||
} | |||
for (RegionTreeDTO regionTreeDTO : regionTreeDtos) { | |||
childrenRegionCodeSet.add(regionTreeDTO.getRegionCode()); | |||
getAllChildrenRegionCodeList(regionTreeDTO.getChildren(), childrenRegionCodeSet); | |||
} | |||
} | |||
@Override | |||
public List<String> getRegionCodes(String regionCode, int regionLevel) { | |||
RegionTreeDTO regionTreeNode = getTreeByRegionAndCode(null, regionCode, regionLevel); | |||
Assert.notNull(regionTreeNode, "不存在此级别区域信息:{}", regionLevel); | |||
List<String> regionCodes = new ArrayList<>(); | |||
if (regionTreeNode != null) { | |||
regionCodes.addAll(CollUtils.fieldList(treeToList(Collections.singletonList(regionTreeNode)), RegionTreeDTO::getRegionCode)); | |||
} | |||
if (!regionCodes.contains(regionCode)) { | |||
regionCodes.add(regionCode); | |||
} | |||
return regionCodes; | |||
} | |||
protected List<RegionTreeDTO> treeToList(List<RegionTreeDTO> treeList) { | |||
ArrayList<RegionTreeDTO> result = new ArrayList<>(); | |||
treeList.forEach(w -> { | |||
result.add(w); | |||
if (CollectionUtils.isNotEmpty(w.getChildren())) { | |||
result.addAll(treeToList(w.getChildren())); | |||
} | |||
}); | |||
return result; | |||
} | |||
/** | |||
* 获取某一个地区开始的层级树 | |||
* | |||
* @param list 地区集合 | |||
* @param code 地区编码 | |||
* @param level 地区层级 | |||
* @return / | |||
*/ | |||
protected RegionTreeDTO getTreeByRegionAndCode(List<RegionTreeDTO> list, String code, int level) { | |||
if (CollectionUtils.isEmpty(list)) { | |||
list = super.getCopyListByLevel(3); | |||
if (CollectionUtils.isEmpty(list)) { | |||
return null; | |||
} | |||
} | |||
Optional<RegionTreeDTO> first = list.stream() | |||
.filter(w -> w.getRegionCode().equals(code) && w.getLevel() == level) | |||
.findFirst(); | |||
if (first.isPresent()) { | |||
return first.get(); | |||
} | |||
for (RegionTreeDTO dto : list) { | |||
if (CollectionUtils.isEmpty(dto.getChildren())) { | |||
continue; | |||
} | |||
RegionTreeDTO temp = getTreeByRegionAndCode(dto.getChildren(), code, level); | |||
if (temp != null) { | |||
return temp; | |||
} | |||
} | |||
return null; | |||
} | |||
@Override | |||
public List<RegionDTO> listParents(String code, int level) { | |||
List<RegionDTO> result = new ArrayList<>(); | |||
RegionDTO dto = regionMap.get(RegionMapKey.of(code, level)); | |||
result.add(0, dto); | |||
if (dto.getParentCode().equals(super.getParentCodeRoot())) { | |||
return result; | |||
} | |||
result.addAll(0, listParents(dto.getParentCode(), dto.getRegionLevel() - 1)); | |||
return result; | |||
} | |||
@Override | |||
public RegionDTO getByCodeAndLevel(String code, int level) { | |||
return regionMap.get(RegionMapKey.of(code, level)); | |||
} | |||
@Override | |||
public List<RegionDTO> getProvincialRegion() { | |||
List<RegionDTO> provincialRegionList = new ArrayList<>(); | |||
regionMap.values().forEach(v -> { | |||
if (v.getRegionCode().equals(v.getParentCode()) && v.getRegionLevel() == 2) { | |||
provincialRegionList.add(v); | |||
} | |||
}); | |||
return provincialRegionList; | |||
} | |||
@Override | |||
public List<RegionDTO> getMunicipalRegion() { | |||
List<RegionDTO> municipalRegionList = new ArrayList<>(); | |||
regionMap.values().forEach(v -> { | |||
if (v.getRegionCode().equals(v.getParentCode()) && v.getRegionLevel() == 3) { | |||
municipalRegionList.add(v); | |||
} | |||
}); | |||
return municipalRegionList; | |||
} | |||
@Override | |||
public Map<String, RegionDTO> getRegionMap() { | |||
Map<String, RegionDTO> regionDtoMap = new ConcurrentHashMap<>(512); | |||
regionMap.forEach((k, v) -> regionDtoMap.put(k.getRegionCode() + "###" + k.getRegionLevel(), v)); | |||
return regionDtoMap; | |||
} | |||
@Override | |||
public Map<String, RegionDTO> getNameRegionMap() { | |||
Map<String, RegionDTO> nameRegionDtoMap = new ConcurrentHashMap<>(512); | |||
regionMap.forEach((k, v) -> nameRegionDtoMap.put(v.getRegionName(), v)); | |||
return nameRegionDtoMap; | |||
} | |||
@Override | |||
public String getUnionPathStr(String code, Integer level) { | |||
if (StringUtils.isBlank(code) || Objects.isNull(level)) { | |||
return null; | |||
} | |||
List<String> unionPathStrList = new ArrayList<>(); | |||
buildUnionPathStrList(code, level, unionPathStrList); | |||
Collections.reverse(unionPathStrList); | |||
if (CollectionUtils.isEmpty(unionPathStrList)) { | |||
return null; | |||
} | |||
return String.join("@@", unionPathStrList); | |||
} | |||
protected void buildUnionPathStrList(String code, Integer level, List<String> unionPathStrList) { | |||
if (level <= 0 || super.getParentCodeRoot().equals(code)) { | |||
return; | |||
} | |||
RegionDTO regionDTO = regionMap.get(RegionMapKey.of(code, level)); | |||
unionPathStrList.add(regionDTO.getRegionCode() + "##" + regionDTO.getRegionName() + "##" + regionDTO.getRegionLevel()); | |||
if (!super.getParentCodeRoot().equals(regionDTO.getParentCode())) { | |||
buildUnionPathStrList(regionDTO.getParentCode(), level - 1, unionPathStrList); | |||
} | |||
} | |||
} |
@@ -38,6 +38,7 @@ import com.ningdatech.pmapi.meeting.service.*; | |||
import com.ningdatech.pmapi.meeting.task.ExpertInviteTask; | |||
import com.ningdatech.pmapi.meta.helper.DictionaryCache; | |||
import com.ningdatech.pmapi.meta.helper.TagCache; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails; | |||
import com.ningdatech.pmapi.user.service.IUserInfoService; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
@@ -65,7 +66,7 @@ import static com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper.getExpertIn | |||
@RequiredArgsConstructor | |||
public class MeetingManage { | |||
private final RegionCacheHelper regionCacheHelper; | |||
private final RegionCacheHelper regionCache; | |||
private final IMeetingService meetingService; | |||
private final IExpertInviteAvoidRuleService inviteAvoidRuleService; | |||
private final IExpertInviteRuleService inviteRuleService; | |||
@@ -453,14 +454,12 @@ public class MeetingManage { | |||
}); | |||
} | |||
if (StrUtil.isNotEmpty(randomRule.getIntentionRegionCode())) { | |||
// TODO 履职意向地 | |||
/*List<RegionDTO> intentionRegions = regionCache.listParents(randomRule.getIntentionRegionCode(), randomRule.getIntentionRegionLevel()); | |||
randomRule.setIntentionRegions(intentionRegions);*/ | |||
List<RegionDTO> intentionRegions = regionCache.listParents(randomRule.getIntentionRegionCode(), randomRule.getIntentionRegionLevel()); | |||
randomRule.setIntentionRegions(intentionRegions); | |||
} | |||
if (StrUtil.isNotEmpty(randomRule.getExpertRegionCode())) { | |||
// TODO 专家层级 | |||
/*List<RegionDTO> expertRegions = regionCache.listParents(randomRule.getExpertRegionCode(), randomRule.getExpertRegionLevel()); | |||
randomRule.setExpertRegions(expertRegions);*/ | |||
List<RegionDTO> expertRegions = regionCache.listParents(randomRule.getExpertRegionCode(), randomRule.getExpertRegionLevel()); | |||
randomRule.setExpertRegions(expertRegions); | |||
} | |||
result.getRandomRules().add(randomRule); | |||
}); | |||
@@ -6,9 +6,9 @@ import cn.hutool.core.util.IdUtil; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.google.common.collect.Maps; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.pmapi.common.constant.RegionConst; | |||
import com.ningdatech.pmapi.common.enumeration.ProjectProcessStageEnum; | |||
import com.ningdatech.pmapi.scheduler.contants.TaskContant; | |||
import com.ningdatech.pmapi.sys.contant.RegionConst; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import com.ningdatech.pmapi.sys.service.IRegionService; | |||
import com.wflow.bean.dto.WflowModelHistorysDto; | |||
@@ -53,7 +53,7 @@ public class InitProcessTask { | |||
//1.查出丽水市下的 区县 分别去初始化 表单和流程配置数据 | |||
List<Region> regions = regionService.list(Wrappers.lambdaQuery(Region.class) | |||
.eq(Region::getDeleted,Boolean.FALSE) | |||
.eq(Region::getParentCode, RegionConst.LS_REGION_CODE)); | |||
.eq(Region::getParentCode, RegionConst.RC_LS)); | |||
if(CollUtil.isEmpty(regions)){ | |||
throw new BizException("丽水地区数据为空 任务结束!"); | |||
@@ -1,26 +0,0 @@ | |||
package com.ningdatech.pmapi.sys.contant; | |||
/** | |||
* <p> | |||
* 地区常量 | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 18:54 2023/1/28 | |||
*/ | |||
public interface RegionConst { | |||
Integer FIRST_LEVEL = 1; | |||
Integer SECOND_LEVEL = 2; | |||
Integer THIRD_LEVEL = 3; | |||
Long EMPTY_PARENT_ID = 0L; | |||
/** | |||
* 丽水地区CODE | |||
*/ | |||
String LS_REGION_CODE = "331100"; | |||
} |
@@ -8,10 +8,9 @@ import lombok.RequiredArgsConstructor; | |||
import org.springframework.validation.annotation.Validated; | |||
import org.springframework.web.bind.annotation.GetMapping; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.web.bind.annotation.RequestParam; | |||
import org.springframework.web.bind.annotation.RestController; | |||
import java.util.List; | |||
/** | |||
* <p> | |||
* 前端控制器 | |||
@@ -31,8 +30,9 @@ public class RegionController { | |||
@GetMapping("/tree") | |||
@ApiOperation("获取区域编码的树状结构") | |||
public List<RegionTreeVO> getRegionTree() { | |||
return regionManage.getRegionTree(); | |||
public RegionTreeVO getRegionTree(@RequestParam(required = false) String regionCode, | |||
@RequestParam(required = false) Integer regionLevel) { | |||
return regionManage.getRegionTree(regionCode, regionLevel); | |||
} | |||
} |
@@ -1,5 +1,6 @@ | |||
package com.ningdatech.pmapi.sys.convert; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionTreeDTO; | |||
@@ -32,6 +33,7 @@ public class RegionConverter { | |||
dto.setDeleted(region.getDeleted()); | |||
dto.setGovUnit(region.getGovUnit()); | |||
dto.setParentId(region.getParentId()); | |||
dto.setRegionCodePath(region.getRegionCodePath()); | |||
dto.unionCode(); | |||
return dto; | |||
} | |||
@@ -56,6 +58,19 @@ public class RegionConverter { | |||
return treeDto; | |||
} | |||
public static RegionTreeVO toRegionTreeVO(RegionDTO region) { | |||
RegionTreeVO node = new RegionTreeVO(); | |||
node.setRegionLevel(region.getRegionLevel()); | |||
node.setName(region.getRegionName()); | |||
node.setParentCode(region.getParentCode()); | |||
node.setRegionCode(region.getRegionCode()); | |||
node.setUnionCode(region.getUnionCode()); | |||
node.setId(region.getId()); | |||
node.setUnionCode(region.getUnionCode()); | |||
node.setGovUnit(region.getGovUnit()); | |||
return node; | |||
} | |||
public static List<RegionTreeVO> toRegionTree(Long parentId, Map<Long, List<RegionDTO>> regions, | |||
boolean showDeleted) { | |||
List<RegionTreeVO> treeList = new ArrayList<>(); | |||
@@ -64,19 +79,12 @@ public class RegionConverter { | |||
if (!showDeleted && region.getDeleted()) { | |||
continue; | |||
} | |||
RegionTreeVO treeNode = new RegionTreeVO(); | |||
treeNode.setRegionLevel(region.getRegionLevel()); | |||
treeNode.setName(region.getRegionName()); | |||
treeNode.setParentCode(region.getParentCode()); | |||
treeNode.setRegionCode(region.getRegionCode()); | |||
RegionTreeVO node = toRegionTreeVO(region); | |||
List<RegionDTO> regionList = regions.get(region.getId()); | |||
if (CollectionUtils.isNotEmpty(regionList)) { | |||
treeNode.setChildren(toRegionTree(region.getId(), regions, showDeleted)); | |||
if (CollUtil.isNotEmpty(regionList)) { | |||
node.setChildren(toRegionTree(region.getId(), regions, showDeleted)); | |||
} | |||
treeNode.setId(region.getId()); | |||
treeNode.setUnionCode(region.getUnionCode()); | |||
treeNode.setGovUnit(region.getGovUnit()); | |||
treeList.add(treeNode); | |||
treeList.add(node); | |||
} | |||
return treeList; | |||
} | |||
@@ -1,14 +1,10 @@ | |||
package com.ningdatech.pmapi.sys.manage; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.pmapi.sys.convert.RegionConverter; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.common.helper.RegionCacheHelper; | |||
import com.ningdatech.pmapi.sys.model.vo.RegionTreeVO; | |||
import com.ningdatech.pmapi.sys.service.IRegionService; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.stereotype.Component; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* <p> | |||
@@ -23,13 +19,10 @@ import java.util.Map; | |||
public class RegionManage { | |||
private final IRegionService regionService; | |||
private final RegionCacheHelper regionCache; | |||
private final static Long ROOT_PARENT_ID = 0L; | |||
public List<RegionTreeVO> getRegionTree() { | |||
List<RegionDTO> regions = regionService.all(); | |||
Map<Long, List<RegionDTO>> regionMap = CollUtils.group(regions, RegionDTO::getParentId); | |||
return RegionConverter.toRegionTree(ROOT_PARENT_ID, regionMap, false); | |||
public RegionTreeVO getRegionTree(String regionCode, Integer regionLevel) { | |||
return regionCache.getRegionTree(regionCode, regionLevel); | |||
} | |||
} |
@@ -49,6 +49,8 @@ public class RegionDTO { | |||
private Long parentId; | |||
private String regionCodePath; | |||
public void unionCode() { | |||
this.unionCode = String.format("%s##%s##%s", this.regionCode, this.regionName, this.regionLevel); | |||
} | |||
@@ -41,6 +41,8 @@ public class Region implements Serializable { | |||
private LocalDateTime updateOn; | |||
private String regionCodePath; | |||
private Boolean deleted; | |||
} |
@@ -24,6 +24,15 @@ public interface IRegionService extends IService<Region> { | |||
List<RegionDTO> all(); | |||
/** | |||
* 查询区域 | |||
* | |||
* @param regionCode 区域编码 | |||
* @param regionLevel 区域层级 | |||
* @return {@link Region} | |||
*/ | |||
Region getOne(String regionCode, int regionLevel); | |||
/** | |||
* 查询大于等与该级别的所有区域 | |||
* | |||
* @param regionLevel | |||
@@ -4,9 +4,9 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.pmapi.sys.convert.RegionConverter; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.mapper.RegionMapper; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import com.ningdatech.pmapi.sys.service.IRegionService; | |||
import org.springframework.stereotype.Service; | |||
@@ -29,6 +29,13 @@ public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> impleme | |||
} | |||
@Override | |||
public Region getOne(String regionCode, int regionLevel) { | |||
return getOne(Wrappers.lambdaQuery(Region.class) | |||
.eq(Region::getRegionCode, regionCode) | |||
.eq(Region::getRegionLevel, regionLevel)); | |||
} | |||
@Override | |||
public List<RegionDTO> listGeLevel(int regionLevel) { | |||
List<Region> regionsByLevel = lambdaQuery().ne(Region::getId, -1) | |||
.le(Region::getRegionLevel, regionLevel).list(); | |||
@@ -0,0 +1,58 @@ | |||
package com.ningdatech.pmapi.sys.service; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.pmapi.AppTests; | |||
import com.ningdatech.pmapi.common.helper.RegionCacheHelper; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import org.junit.Test; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.concurrent.atomic.AtomicLong; | |||
/** | |||
* <p> | |||
* IRegionServiceTest | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 16:57 2023/3/1 | |||
*/ | |||
public class IRegionServiceTest extends AppTests { | |||
@Autowired | |||
private IRegionService regionService; | |||
@Test | |||
public void init() { | |||
AtomicLong idIncr = new AtomicLong(1); | |||
Map<Integer, List<Region>> map = CollUtils.group(regionService.list(), Region::getRegionLevel); | |||
regionService.remove(null); | |||
map.keySet().stream().sorted().forEach(w -> { | |||
List<Region> list = new ArrayList<>(); | |||
List<Region> regions = map.get(w); | |||
for (Region region : regions) { | |||
if (w == 1) { | |||
region.setRegionCodePath(region.getParentCode() + "," + region.getRegionCode()); | |||
region.setParentId(0L); | |||
} else { | |||
Region parent = regionService.getOne(Wrappers.lambdaQuery(Region.class) | |||
.eq(Region::getRegionCode, region.getParentCode()) | |||
.eq(Region::getRegionLevel, region.getRegionLevel() - 1)); | |||
region.setRegionCodePath(parent.getRegionCodePath() + "," + region.getRegionCode()); | |||
region.setParentId(parent.getId()); | |||
} | |||
region.setId(idIncr.getAndIncrement()); | |||
list.add(region); | |||
} | |||
regionService.saveBatch(list); | |||
System.out.println("============================================================================"); | |||
}); | |||
} | |||
} |