This commit is contained in:
zt
2025-03-10 16:33:17 +08:00
parent 0dd222e9f3
commit e21644c5c9
19 changed files with 413 additions and 190 deletions

View File

@ -1,4 +1,4 @@
package com.ruoyi.common.core.domain.model;
package com.ruoyi.common.core.domain;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -8,7 +8,7 @@ import java.util.List;
@ApiModel("地区节点 Response VO")
@Data
public class AreaNodeRespVO {
public class AreaNode {
@ApiModelProperty("编号")
private Integer id;
@ -19,6 +19,6 @@ public class AreaNodeRespVO {
/**
* 子节点
*/
private List<AreaNodeRespVO> children;
private List<AreaNode> children;
}

View File

@ -1,20 +1,8 @@
package com.ruoyi.common.utils;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.csv.CsvRow;
import cn.hutool.core.text.csv.CsvUtil;
import com.ruoyi.common.core.domain.Area;
import com.ruoyi.common.enums.AreaType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 区域工具类
*
@ -24,167 +12,167 @@ import java.util.stream.Collectors;
@Component
public class AreaUtils {
/**
* 初始化 SEARCHER
*/
@SuppressWarnings("InstantiationOfUtilityClass")
private final static AreaUtils INSTANCE = new AreaUtils();
/**
* Area 内存缓存,提升访问速度
*/
private static Map<Integer, Area> areas;
private AreaUtils() {
long now = System.currentTimeMillis();
areas = new HashMap<>();
areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0, null, new ArrayList<>()));
try {
List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
if (!rows.isEmpty()) {
rows.remove(0); // 删除 header
for (CsvRow row : rows) {
// 创建 Area 对象
Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)),
null, new ArrayList<>());
// 添加到 areas 中
areas.put(area.getId(), area);
// 构建父子关系
int parentId = Integer.valueOf(row.get(3));
Area parent = areas.get(parentId);
if (parent != null) {
Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
area.setParent(parent);
parent.getChildren().add(area);
} else {
log.warn("区域 {} 的父区域 ID {} 无效", area.getName(), parentId);
}
}
}
} catch (Exception e) {
log.error("加载区域数据时发生错误", e);
}
log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
}
/**
* 获得指定编号对应的区域
*
* @param id 区域编号
* @return 区域
*/
public static Area getArea(Integer id) {
return areas.get(id);
}
/**
* 获取所有节点的全路径名称如:河南省/石家庄市/新华区
*
* @param areas 地区树
* @return 所有节点的全路径名称
*/
public static List<String> getAreaNodePathList(List<Area> areas) {
List<String> paths = new ArrayList<>();
areas.forEach(area -> getAreaNodePathList(area, "", paths));
return paths;
}
/**
* 构建一棵树的所有节点的全路径名称,并将其存储为 "祖先/父级/子级" 的形式
*
* @param node 父节点
* @param path 全路径名称
* @param paths 全路径名称列表,省份/城市/地区
*/
private static void getAreaNodePathList(Area node, String path, List<String> paths) {
if (node == null) {
return;
}
// 构建当前节点的路径
String currentPath = path.isEmpty() ? node.getName() : path + "/" + node.getName();
paths.add(currentPath);
// 递归遍历子节点
for (Area child : node.getChildren()) {
getAreaNodePathList(child, currentPath, paths);
}
}
/**
* 格式化区域
*
* @param id 区域编号
* @return 格式化后的区域
*/
public static String format(Integer id) {
return format(id, " ");
}
/**
* 格式化区域
*
* 例如说:
* 1. id = “静安区”时:上海 上海市 静安区
* 2. id = “上海市”时:上海 上海市
* 3. id = “上海”时:上海
* 4. id = “美国”时:美国
* 当区域在中国时,默认不显示中国
*
* @param id 区域编号
* @param separator 分隔符
* @return 格式化后的区域
*/
public static String format(Integer id, String separator) {
// 获得区域
Area area = areas.get(id);
if (area == null) {
return null;
}
// 格式化
StringBuilder sb = new StringBuilder();
for (int i = 0; i < AreaType.values().length; i++) { // 避免死循环
sb.insert(0, area.getName());
// “递归”父节点
area = area.getParent();
if (area == null
||
AreaType.getSkipType().contains(area.getId())) { // 跳过父节点为中国的情况
break;
}
sb.insert(0, separator);
}
return sb.toString();
}
public static AreaUtils getInstance() {
return INSTANCE;
}
public static <S, T> List<T> toBean(List<S> source, Class<T> targetType) {
if (source == null) {
return null;
}
return convertList(source, s -> toBean(s, targetType));
}
public static <T> T toBean(Object source, Class<T> targetClass) {
return BeanUtil.toBean(source, targetClass);
}
public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func) {
if (CollUtil.isEmpty(from)) {
return new ArrayList<>();
}
return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toList());
}
// /**
// * 初始化 SEARCHER
// */
// @SuppressWarnings("InstantiationOfUtilityClass")
// private final static AreaUtils INSTANCE = new AreaUtils();
//
// /**
// * Area 内存缓存,提升访问速度
// */
// private static Map<Integer, Area> areas;
//
// private AreaUtils() {
// long now = System.currentTimeMillis();
// areas = new HashMap<>();
// areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0, null, new ArrayList<>()));
//
// try {
// List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
// if (!rows.isEmpty()) {
// rows.remove(0); // 删除 header
// for (CsvRow row : rows) {
// // 创建 Area 对象
// Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)),
// null, new ArrayList<>());
// // 添加到 areas 中
// areas.put(area.getId(), area);
//
// // 构建父子关系
// int parentId = Integer.valueOf(row.get(3));
// Area parent = areas.get(parentId);
// if (parent != null) {
// Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
// area.setParent(parent);
// parent.getChildren().add(area);
// } else {
// log.warn("区域 {} 的父区域 ID {} 无效", area.getName(), parentId);
// }
// }
// }
// } catch (Exception e) {
// log.error("加载区域数据时发生错误", e);
// }
//
// log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
// }
//
// /**
// * 获得指定编号对应的区域
// *
// * @param id 区域编号
// * @return 区域
// */
// public static Area getArea(Integer id) {
// return areas.get(id);
// }
//
//
//
// /**
// * 获取所有节点的全路径名称如:河南省/石家庄市/新华区
// *
// * @param areas 地区树
// * @return 所有节点的全路径名称
// */
// public static List<String> getAreaNodePathList(List<Area> areas) {
// List<String> paths = new ArrayList<>();
// areas.forEach(area -> getAreaNodePathList(area, "", paths));
// return paths;
// }
//
// /**
// * 构建一棵树的所有节点的全路径名称,并将其存储为 "祖先/父级/子级" 的形式
// *
// * @param node 父节点
// * @param path 全路径名称
// * @param paths 全路径名称列表,省份/城市/地区
// */
// private static void getAreaNodePathList(Area node, String path, List<String> paths) {
// if (node == null) {
// return;
// }
// // 构建当前节点的路径
// String currentPath = path.isEmpty() ? node.getName() : path + "/" + node.getName();
// paths.add(currentPath);
// // 递归遍历子节点
// for (Area child : node.getChildren()) {
// getAreaNodePathList(child, currentPath, paths);
// }
// }
//
// /**
// * 格式化区域
// *
// * @param id 区域编号
// * @return 格式化后的区域
// */
// public static String format(Integer id) {
// return format(id, " ");
// }
//
// /**
// * 格式化区域
// *
// * 例如说:
// * 1. id = “静安区”时:上海 上海市 静安区
// * 2. id = “上海市”时:上海 上海市
// * 3. id = “上海”时:上海
// * 4. id = “美国”时:美国
// * 当区域在中国时,默认不显示中国
// *
// * @param id 区域编号
// * @param separator 分隔符
// * @return 格式化后的区域
// */
// public static String format(Integer id, String separator) {
// // 获得区域
// Area area = areas.get(id);
// if (area == null) {
// return null;
// }
//
// // 格式化
// StringBuilder sb = new StringBuilder();
// for (int i = 0; i < AreaType.values().length; i++) { // 避免死循环
// sb.insert(0, area.getName());
// // “递归”父节点
// area = area.getParent();
// if (area == null
// ||
// AreaType.getSkipType().contains(area.getId())) { // 跳过父节点为中国的情况
// break;
// }
// sb.insert(0, separator);
// }
// return sb.toString();
// }
//
//
//
// public static AreaUtils getInstance() {
// return INSTANCE;
// }
//
// public static <S, T> List<T> toBean(List<S> source, Class<T> targetType) {
// if (source == null) {
// return null;
// }
// return convertList(source, s -> toBean(s, targetType));
// }
//
// public static <T> T toBean(Object source, Class<T> targetClass) {
// return BeanUtil.toBean(source, targetClass);
// }
//
// public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func) {
// if (CollUtil.isEmpty(from)) {
// return new ArrayList<>();
// }
// return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toList());
// }
//
}