Compare commits

...

2 Commits

  1. 16
      dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDepartBoundaryController.java
  2. 7
      dk-modules/system/src/main/java/org/dromara/system/domain/SysDepartBoundary.java
  3. 1
      dk-modules/system/src/main/java/org/dromara/system/mapper/SysDepartBoundaryMapper.java
  4. 4
      dk-modules/system/src/main/java/org/dromara/system/service/ISysDepartBoundaryService.java
  5. 33
      dk-modules/system/src/main/java/org/dromara/system/service/impl/SysDepartBoundaryServiceImpl.java
  6. 140
      dk-modules/system/src/main/java/org/dromara/system/utils/KmlParserUtil.java
  7. 78
      dk-modules/system/src/main/resources/mapper/system/SysDepartBoundaryMapper.xml

16
dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDepartBoundaryController.java

@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
@ -58,6 +59,7 @@ public class SysDepartBoundaryController extends BaseController {
* 解析shp文件
* @return
*/
@RepeatSubmit()
@Operation(summary ="新增部门区域",description = "新增部门区域(areaType: 0:市级 1:区级(县) 2:镇级(街道) 3:村级)")
@RequestMapping(value = "/{areaType}/{parentId}/upload", method = RequestMethod.POST)
public R<Void> uploadShpFile(@RequestParam("file") MultipartFile file,
@ -67,6 +69,20 @@ public class SysDepartBoundaryController extends BaseController {
}
/**
* 根据经纬度查询部门信息
* @param latlng
* @return
*/
@Operation(summary ="根据经纬度查询部门信息",description = "根据经纬度查询部门信息")
@GetMapping(value = "/location/list")
public R<List<SysDepartBoundary>> listDepartBoundaryByLngAndLat(@RequestParam("lat") Double lat,
@RequestParam("lng") Double lng) {
List<SysDepartBoundary> listJson = departBoundaryService.listDepartBoundaryByLngAndLat(lng,lat);
return R.ok(listJson);
}
/**
* 通过id删除
*

7
dk-modules/system/src/main/java/org/dromara/system/domain/SysDepartBoundary.java

@ -23,7 +23,7 @@ public class SysDepartBoundary extends BaseEntity {
/**ID*/
@TableId(type = IdType.AUTO)
private String id;
private Long id;
/**机构ID*/
private Long deptId;
@ -42,6 +42,11 @@ public class SysDepartBoundary extends BaseEntity {
*/
private Integer areaType;
/**
* 父类id
*/
private Long parentId;
/**删除状态(0,正常,1已删除)*/
private String delFlag;

1
dk-modules/system/src/main/java/org/dromara/system/mapper/SysDepartBoundaryMapper.java

@ -26,4 +26,5 @@ public interface SysDepartBoundaryMapper extends BaseMapper<SysDepartBoundary> {
String listJson(@Param("deptId") String deptId);
List<SysDepartBoundary> listDepartBoundaryByLngAndLat(@Param("lng") Double lng,@Param("lat") Double lat);
}

4
dk-modules/system/src/main/java/org/dromara/system/service/ISysDepartBoundaryService.java

@ -22,11 +22,13 @@ public interface ISysDepartBoundaryService extends IService<SysDepartBoundary>{
boolean uploadShpFile(MultipartFile file,Integer areaType,Long parentId);
boolean deleteDepartBoundary(String id);
boolean deleteDepartBoundary(String deptId);
boolean updateDepartBoundary(SysDepartBoundary departBoundary);
boolean addDepartBoundary(SysDepartBoundary departBoundary);
List<SysDepartBoundaryBo> listJson(SysDepartBoundary departBoundary);
List<SysDepartBoundary> listDepartBoundaryByLngAndLat(Double lng, Double lat);
}

33
dk-modules/system/src/main/java/org/dromara/system/service/impl/SysDepartBoundaryServiceImpl.java

@ -1,6 +1,7 @@
package org.dromara.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -20,6 +21,7 @@ import org.dromara.system.service.ISysDepartBoundaryService;
import org.dromara.system.service.ISysDeptService;
import org.dromara.system.service.ISysVectorDictService;
import org.dromara.system.utils.BatchProcessorUtil;
import org.dromara.system.utils.KmlParserUtil;
import org.dromara.system.utils.KmzParserUtil;
import org.dromara.system.utils.ShpAnalysisUtil;
import org.dromara.common.core.exception.ServiceException;
@ -104,8 +106,11 @@ public class SysDepartBoundaryServiceImpl extends ServiceImpl<SysDepartBoundaryM
//1、首先调用解析工具拿到解析的字段集合
if (file.getOriginalFilename().endsWith(".zip")) {
mapList = ShpAnalysisUtil.analysisShpFile(file.getInputStream());
} else if (file.getOriginalFilename().endsWith(".kmz") || file.getOriginalFilename().endsWith(".ovkmz")) {
List<KmzResult> kmzResults = KmzParserUtil.parseKmz(file.getInputStream());
List<Map<String, String>> kmzList = new ArrayList<>();
@ -120,9 +125,11 @@ public class SysDepartBoundaryServiceImpl extends ServiceImpl<SysDepartBoundaryM
kmzList.add(map);
});
mapList = kmzList;
}
} else if (file.getOriginalFilename().endsWith(".kml") || file.getOriginalFilename().endsWith(".ovkml")) {
mapList = KmlParserUtil.parseKml(file.getInputStream());
}
// 3. 构建字典map
List<SysVectorDict> fieldsInfoList = vectorDictService.listVectorField();
@ -219,16 +226,31 @@ public class SysDepartBoundaryServiceImpl extends ServiceImpl<SysDepartBoundaryM
return List.of(child,parent);
}
/**
* 根据经纬度查询部门信息
* @param lng
* @param lat
* @return
*/
@Override
public List<SysDepartBoundary> listDepartBoundaryByLngAndLat(Double lng, Double lat) {
return this.baseMapper.listDepartBoundaryByLngAndLat(lng,lat);
}
@Override
public boolean deleteDepartBoundary(String id) {
SysDepartBoundary departBoundary = this.baseMapper.selectById(id);
public boolean deleteDepartBoundary(String deptId) {
LambdaQueryWrapper<SysDepartBoundary> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysDepartBoundary::getDeptId,deptId);
List<SysDepartBoundary> sysDepartBoundaries = this.baseMapper.selectList(wrapper);
if (ObjectUtil.isEmpty(departBoundary)) {
if (ObjectUtil.isEmpty(sysDepartBoundaries)) {
throw new ServiceException("实体不存在!");
}
return this.baseMapper.deleteById(departBoundary.getId())>0;
return this.baseMapper.deleteByIds(sysDepartBoundaries.stream().map(SysDepartBoundary::getId).distinct().toList())>0;
}
@ -277,6 +299,7 @@ public class SysDepartBoundaryServiceImpl extends ServiceImpl<SysDepartBoundaryM
}
private void createBoundary(SysDepartBoundary businessDepartBoundary, Map<String, List<Map<String, Object>>> namePathMap, String divisionName, Integer areaType, Long parentId) {
businessDepartBoundary.setParentId(parentId);
//判断是否存在表中,在表中更新部门区域中的部门id信息
if (ObjectUtil.isNotEmpty(namePathMap.get(divisionName))){
Map<String, Object> objectMap = namePathMap.get(divisionName).get(0);

140
dk-modules/system/src/main/java/org/dromara/system/utils/KmlParserUtil.java

@ -0,0 +1,140 @@
package org.dromara.system.utils;
import cn.hutool.core.util.ObjectUtil;
import java.io.*;
import java.util.*;
/**
* KML文件解析器
* KML是Google Earth使用的标记语言格式
*/
public class KmlParserUtil {
/**
* 从KML内容中提取所有Placemark数据
*
* @param kmlContent KML内容
* @return 包含name和coordinates的Map列表
*/
public static List<Map<String, String>> extractPlacemarks(String kmlContent) {
List<Map<String, String>> placemarkList = new ArrayList<>();
int startIndex = 0;
while (true) {
// 查找Placemark开始标签
int startPlacemark = kmlContent.indexOf("<Placemark>", startIndex);
if (startPlacemark == -1) {
break;
}
// 查找Placemark结束标签
int endPlacemark = kmlContent.indexOf("</Placemark>", startPlacemark);
if (endPlacemark == -1) {
break;
}
// 提取当前Placemark的内容
String placemarkContent = kmlContent.substring(startPlacemark, endPlacemark + "</Placemark>".length());
// 提取name
String name = "";
int nameStart = placemarkContent.indexOf("<name>");
int nameEnd = placemarkContent.indexOf("</name>");
if (nameStart != -1 && nameEnd != -1) {
name = placemarkContent.substring(nameStart + "<name>".length(), nameEnd).trim();
}
// 提取coordinates
String coordinates = "";
int coordStart = placemarkContent.indexOf("<coordinates>");
int coordEnd = placemarkContent.indexOf("</coordinates>");
if (coordStart != -1 && coordEnd != -1) {
coordinates = placemarkContent.substring(coordStart + "<coordinates>".length(), coordEnd).trim();
}
//提取<Data name ="name">
if (ObjectUtil.isEmpty(name)){
int dataStart = placemarkContent.indexOf("Data name =\"name\"");
if (dataStart != -1) {
int valueStart = placemarkContent.indexOf("<value>", dataStart);
int valueEnd = placemarkContent.indexOf("</value>", valueStart);
if (valueStart != -1 && valueEnd != -1) {
name = placemarkContent.substring(valueStart + "<value>".length(), valueEnd).trim();
}
}
}
// 创建Map并添加到列表
Map<String, String> placemarkMap = new HashMap<>();
placemarkMap.put("XZQMC", name);
String wkt = convertToWKT(coordinates);
placemarkMap.put("the_geom", wkt);
placemarkList.add(placemarkMap);
// 更新搜索起始位置
startIndex = endPlacemark + "</Placemark>".length();
}
return placemarkList;
}
/**
* 将坐标字符串转换为WKTWell-Known Text格式
*
* @param coordinates 坐标字符串
* @return WKT格式的字符串
*/
public static String convertToWKT(String coordinates) {
if (coordinates == null || coordinates.trim().isEmpty()) {
return "";
}
// 构建WKT格式的多边形
StringBuilder wkt = new StringBuilder("POLYGON((");
String[] coordPairs = coordinates.trim().split("\\s+");
// 处理每个坐标对
for (int i = 0; i < coordPairs.length; i++) {
String[] coords = coordPairs[i].split(",");
if (coords.length >= 2) {
wkt.append(coords[0]).append(" ").append(coords[1]);
if (i < coordPairs.length - 1) {
wkt.append(", ");
}
}
}
wkt.append("))");
StringBuffer polygonSb = new StringBuffer("GEOMETRYCOLLECTION(");
polygonSb.append(wkt);
polygonSb.append(")");
return polygonSb.toString();
}
/**
* 解析KML文件的主方法
*
* @param inputStream KML文件的输入流
* @return 包含name和coordinates的Map列表
* @throws IOException 如果文件读取或处理过程中发生错误
*/
public static List<Map<String, String>> parseKml(InputStream inputStream) throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
StringBuilder kmlContent = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
kmlContent.append(line).append("\n");
}
return extractPlacemarks(kmlContent.toString());
}
}
}

78
dk-modules/system/src/main/resources/mapper/system/SysDepartBoundaryMapper.xml

@ -3,27 +3,52 @@
<mapper namespace="org.dromara.system.mapper.SysDepartBoundaryMapper">
<select id="listSysDepartBoundary" resultType="org.dromara.system.domain.SysDepartBoundary">
SELECT
db.id,
db.dept_id,
db.dept_name,
db.type,
db.name_path,
CONCAT(
REPLACE ( REPLACE ( REPLACE ( REPLACE ( ST_AsText ( db.boundary ), 'GEOMETRYCOLLECTION(POLYGON((', '[[' ), ')))', ']]' ), ',', '],[' ), ' ', ',' )
) AS boundary,
db.create_by,
db.create_time
t.*,
(
SELECT
JSON_OBJECT(
'type', 'FeatureCollection',
'features', COALESCE (
JSON_ARRAYAGG(
JSON_OBJECT(
'type', 'Feature',
'properties', JSON_OBJECT(
'deptId', l.dept_id,
'deptName', l.dept_name,
'name', l.name_path,
'community_name', l.name_path
),
'geometry', ST_AsGeoJSON(l.boundary)
)
),
JSON_ARRAY() -- 如果没有数据,则返回空数组
)
) AS landCategoriesJson
FROM
sys_depart_boundary db
LEft JOIN sys_dept d on db.dept_id = d.dept_id
sys_depart_boundary l
WHERE
l.dept_id = t.dept_id
) AS boundary
FROM
(
SELECT
dept_id,
MAX(dept_name) AS dept_name,
area_type,
MAX(name_path) as name_path,
MAX(create_time) AS create_time
FROM
sys_depart_boundary
GROUP BY
dept_id, area_type
) t
<where>
<if test="condition.deptId != null and condition.deptId != ''">
and (db.dept_id = #{condition.deptId} or d.parent_id = #{condition.deptId})
</if>
<if test="condition.namePath != null and condition.namePath != ''">
and db.name_path like concat(concat('%',#{condition.namePath}),'%')
and t.name_path like concat(concat('%',#{condition.namePath}),'%')
</if>
<if test="condition.deptName != null and condition.deptName != ''">
and t.dept_name like concat(concat('%',#{condition.deptName}),'%')
</if>
</where>
</select>
@ -33,7 +58,7 @@
db.id,
db.dept_id,
db.dept_name,
db.type,
db.area_type,
db.name_path,
CONCAT(
REPLACE ( REPLACE ( REPLACE ( REPLACE ( ST_AsText ( db.boundary ), 'GEOMETRYCOLLECTION(POLYGON((', '[[' ), ')))', ']]' ), ',', '],[' ), ' ', ',' )
@ -62,7 +87,7 @@
db.id,
db.dept_id,
db.dept_name,
db.type,
db.area_type,
db.name_path,
CONCAT(
REPLACE ( REPLACE ( REPLACE ( REPLACE ( ST_AsText ( db.boundary ), 'GEOMETRYCOLLECTION(POLYGON((', '[[' ), ')))', ']]' ), ',', '],[' ), ' ', ',' )
@ -82,6 +107,7 @@
name_path,
boundary,
area_type,
parent_id,
create_by,
create_time,
update_by,
@ -95,6 +121,7 @@
#{item.namePath},
ST_GeomFromText(#{item.boundary}),
#{item.areaType},
#{item.parentId},
#{item.createBy},
#{item.createTime},
#{item.updateBy},
@ -135,4 +162,17 @@
d.dept_id = #{deptId}
</select>
<select id="listDepartBoundaryByLngAndLat" resultType="org.dromara.system.domain.SysDepartBoundary">
select
db.id,
db.dept_id,
db.dept_name,
db.area_type,
db.name_path
FROM
sys_depart_boundary db
WHERE ST_Contains(db.boundary, ST_GeomFromText(CONCAT('POINT(', #{lng}, ' ', #{lat}, ')')))
ORDER BY area_type
</select>
</mapper>

Loading…
Cancel
Save