package com.tcm.training.admin.app.register.service; import com.tcm.training.admin.app.register.entity.SysRegion; import com.tcm.training.admin.app.register.mapper.SysRegionMapper; import com.tcm.training.admin.app.register.vo.AppRegisterRegionDatasetVO; import com.tcm.training.admin.app.register.vo.AppRegisterRegionOptionVO; import com.tcm.training.admin.app.register.vo.AppRegisterRegionPickerOptionVO; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * APP 注册行政区划服务,负责三级联动查询与海诊通地区数据归一化。 */ @Service public class AppRegisterRegionService { private static final long ROOT_PARENT_ID = 0L; private final SysRegionMapper sysRegionMapper; /** * 注入行政区划查询 Mapper。 */ public AppRegisterRegionService(SysRegionMapper sysRegionMapper) { this.sysRegionMapper = sysRegionMapper; } /** * 按父级地区编码查询下一级行政区划。 */ public List listRegions(String parentCode) { Long parentId = resolveParentId(parentCode); if (parentId == null) { return Collections.emptyList(); } List regions = sysRegionMapper.selectByParentId(parentId); if (regions == null || regions.isEmpty()) { return Collections.emptyList(); } List options = new ArrayList(regions.size()); for (SysRegion region : regions) { options.add(toRegionOption(region)); } return options; } /** * 构造兼容 APP 滚轮地区选择器的数据集。 */ public AppRegisterRegionDatasetVO buildRegionDataset() { List regions = sysRegionMapper.selectAllOrdered(); AppRegisterRegionDatasetVO dataset = new AppRegisterRegionDatasetVO(); if (regions == null || regions.isEmpty()) { return dataset; } Map> childrenByParentId = new LinkedHashMap>(); for (SysRegion region : regions) { Long parentId = region.getParentId() == null ? ROOT_PARENT_ID : region.getParentId(); List children = childrenByParentId.get(parentId); if (children == null) { children = new ArrayList(); childrenByParentId.put(parentId, children); } children.add(region); } List provinces = childrenByParentId.get(ROOT_PARENT_ID); if (provinces == null || provinces.isEmpty()) { return dataset; } List provinceOptions = new ArrayList(provinces.size()); List> cityOptions = new ArrayList>(provinces.size()); List>> areaOptions = new ArrayList>>(provinces.size()); for (SysRegion province : provinces) { provinceOptions.add(toPickerOption(province, 1)); List cities = childrenByParentId.get(province.getId()); if (cities == null) { cities = Collections.emptyList(); } List currentCityOptions = new ArrayList(cities.size()); List> currentAreaOptions = new ArrayList>(cities.size()); for (SysRegion city : cities) { currentCityOptions.add(toPickerOption(city, 2)); List districts = childrenByParentId.get(city.getId()); if (districts == null) { districts = Collections.emptyList(); } List currentDistrictOptions = new ArrayList(districts.size()); for (SysRegion district : districts) { if (shouldHideInAppPicker(district)) { continue; } currentDistrictOptions.add(toPickerOption(district, 3)); } currentAreaOptions.add(currentDistrictOptions); } cityOptions.add(currentCityOptions); areaOptions.add(currentAreaOptions); } dataset.setProvinces(provinceOptions); dataset.setCities(cityOptions); dataset.setAreas(areaOptions); return dataset; } /** * APP 地区选择器不展示行政区划占位节点。 */ private boolean shouldHideInAppPicker(SysRegion region) { return region.getName() != null && region.getName().contains("市辖区"); } /** * 将海诊通诊所地区编码或名称归一化为本地三级行政区划。 */ public RegionSelection resolveRegionSelection(String provinceCode, String provinceName, String cityCode, String cityName, String districtCode, String districtName) { SysRegion province = resolveRegionByCode(provinceCode); SysRegion city = resolveRegionByCode(cityCode); SysRegion district = resolveRegionByCode(districtCode); if (district != null && city == null) { city = findRegionById(district.getParentId()); } if (city != null && province == null) { province = findRegionById(city.getParentId()); } province = resolveProvinceRegion(province, provinceName); city = resolveCityRegion(city, province, cityName); if (city != null && province == null) { province = findRegionById(city.getParentId()); } district = resolveDistrictRegion(district, city, districtName); if (district != null && city == null) { city = findRegionById(district.getParentId()); } if (city != null && province == null) { province = findRegionById(city.getParentId()); } if (!isSameParent(city, province)) { city = null; district = null; } if (!isSameParent(district, city)) { district = null; } RegionSelection selection = new RegionSelection(); if (province != null) { selection.setProvinceCode(province.getCode()); selection.setProvinceName(province.getName()); } if (city != null) { selection.setCityCode(city.getCode()); selection.setCityName(city.getName()); } if (district != null) { selection.setDistrictCode(district.getCode()); selection.setDistrictName(district.getName()); } return selection; } /** * 将实体转换为前端下拉选项。 */ private AppRegisterRegionOptionVO toRegionOption(SysRegion region) { AppRegisterRegionOptionVO option = new AppRegisterRegionOptionVO(); option.setId(region.getId()); option.setCode(region.getCode()); option.setName(region.getName()); option.setParentId(region.getParentId()); option.setLevel(resolveRegionLevel(region.getCode())); return option; } /** * 将实体转换为滚轮选择器使用的标签和值。 */ private AppRegisterRegionPickerOptionVO toPickerOption(SysRegion region, int level) { AppRegisterRegionPickerOptionVO option = new AppRegisterRegionPickerOptionVO(); option.setLabel(region.getName()); option.setValue(resolvePickerValue(region.getCode(), level)); return option; } /** * 将数据库 6 位行政区编码转换为前端滚轮选择器的分级编码。 */ private String resolvePickerValue(String code, int level) { if (code == null || code.trim().isEmpty()) { return ""; } if (level == 1 && code.length() >= 2) { return code.substring(0, 2); } if (level == 2 && code.length() >= 4) { return code.substring(0, 4); } return code.length() >= 6 ? code.substring(0, 6) : code; } /** * 计算当前编码所属的行政区层级。 */ private Integer resolveRegionLevel(String code) { if (code == null || code.length() != 6) { return null; } if (code.endsWith("0000")) { return 1; } if (code.endsWith("00")) { return 2; } return 3; } /** * 将父级地区编码转换为父级 ID。 */ private Long resolveParentId(String parentCode) { String normalizedParentCode = trimToNull(parentCode); if (normalizedParentCode == null) { return ROOT_PARENT_ID; } SysRegion parent = sysRegionMapper.selectByCode(normalizedParentCode); return parent == null ? null : parent.getId(); } /** * 优先按编码解析省份,编码缺失时再按名称匹配根节点。 */ private SysRegion resolveProvinceRegion(SysRegion province, String provinceName) { if (province != null) { return province; } return resolveRegionByName(ROOT_PARENT_ID, provinceName); } /** * 优先按编码解析城市,编码无效时回退到省份下的名称匹配。 */ private SysRegion resolveCityRegion(SysRegion city, SysRegion province, String cityName) { if (city != null && (province == null || isSameParent(city, province))) { return city; } if (province == null) { return null; } return resolveRegionByName(province.getId(), cityName); } /** * 优先按编码解析区县,编码无效时回退到城市下的名称匹配。 */ private SysRegion resolveDistrictRegion(SysRegion district, SysRegion city, String districtName) { if (district != null && (city == null || isSameParent(district, city))) { return district; } if (city == null) { return null; } return resolveRegionByName(city.getId(), districtName); } /** * 按编码查询行政区划,空值直接返回空。 */ private SysRegion resolveRegionByCode(String code) { String normalizedCode = trimToNull(code); if (normalizedCode == null) { return null; } return sysRegionMapper.selectByCode(normalizedCode); } /** * 在父节点下按名称精确匹配行政区划。 */ private SysRegion resolveRegionByName(Long parentId, String name) { String normalizedName = trimToNull(name); if (parentId == null || normalizedName == null) { return null; } return sysRegionMapper.selectByParentIdAndName(parentId, normalizedName); } /** * 按主键回查行政区划实体。 */ private SysRegion findRegionById(Long regionId) { if (regionId == null || regionId <= 0) { return null; } return sysRegionMapper.selectById(regionId); } /** * 判断子节点是否归属于指定父节点。 */ private boolean isSameParent(SysRegion child, SysRegion parent) { if (child == null || parent == null) { return true; } return parent.getId() != null && parent.getId().equals(child.getParentId()); } /** * 将空白字符串统一转换为 null。 */ private String trimToNull(String value) { if (value == null) { return null; } String trimmed = value.trim(); return trimmed.isEmpty() ? null : trimmed; } /** * 归一化后的三级行政区划结果。 */ @Getter @Setter @NoArgsConstructor public static class RegionSelection { private String provinceCode; private String provinceName; private String cityCode; private String cityName; private String districtCode; private String districtName; } }