2 Cometimentos

Autor SHA1 Mensagem Data
  Zhao 97b5027656 导入任务 há 5 dias
  Zhao b15d3d8eeb 关闭热部署 há 5 dias
36 ficheiros alterados com 2531 adições e 12 eliminações
  1. +39
    -0
      pom.xml
  2. +5
    -0
      ruoyi-admin/pom.xml
  3. +37
    -1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/business/TTaskImportController.java
  4. +7
    -1
      ruoyi-admin/src/main/resources/application.yml
  5. +53
    -0
      ruoyi-admin/src/test/java/GeoTest.java
  6. +25
    -0
      ruoyi-business/src/main/java/com/ruoyi/business/constants/TaskEnums.java
  7. +2
    -0
      ruoyi-business/src/main/java/com/ruoyi/business/mapper/TGisCjqyMapper.java
  8. +3
    -0
      ruoyi-business/src/main/java/com/ruoyi/business/mapper/TTaskImportMapper.java
  9. +22
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/config/GeoImportTaskConfig.java
  10. +11
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/constants/GeoShpType.java
  11. +72
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/constants/GeoSysDir.java
  12. +149
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoCjqyTask.java
  13. +8
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoDBTaskInterface.java
  14. +14
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoException.java
  15. +46
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoFileSystem.java
  16. +293
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoImportTask.java
  17. +181
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoJtzyTask.java
  18. +174
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoTaskLog.java
  19. +261
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoTaskQueue.java
  20. +179
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoZyhycgTask.java
  21. +13
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/object/GeoLogInfo.java
  22. +247
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/service/GeoImportHandlerService.java
  23. +69
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/structs/GeoCJQY.java
  24. +90
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/structs/GeoDK.java
  25. +107
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/structs/GeoJTZY.java
  26. +80
    -0
      ruoyi-business/src/main/java/com/ruoyi/geo/structs/GeoZYHYCG.java
  27. +1
    -0
      ruoyi-business/src/main/java/com/ruoyi/resource/mapper/TResourceLandMapper.java
  28. +2
    -0
      ruoyi-business/src/main/java/com/ruoyi/resource/mapper/TResourceOperationMapper.java
  29. +9
    -5
      ruoyi-business/src/main/resources/mapper/business/TGisCjqyMapper.xml
  30. +11
    -0
      ruoyi-business/src/main/resources/mapper/business/TTaskImportMapper.xml
  31. +9
    -5
      ruoyi-business/src/main/resources/mapper/resource/TResourceLandMapper.xml
  32. +4
    -0
      ruoyi-business/src/main/resources/mapper/resource/TResourceOperationMapper.xml
  33. +17
    -0
      ruoyi-common/pom.xml
  34. +178
    -0
      ruoyi-common/src/main/java/com/ruoyi/common/geo/GeoParser.java
  35. +5
    -0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/DecimalUtils.java
  36. +108
    -0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/DB.java

+ 39
- 0
pom.xml Ver ficheiro

@@ -40,6 +40,7 @@
<de.odysseus.juel.version>2.1.3</de.odysseus.juel.version>
<httpclient.version>4.5.13</httpclient.version>
<net.coobird.version>0.4.8</net.coobird.version>
<geotools.version>20.0</geotools.version>
</properties>

<!-- 依赖声明 -->
@@ -230,6 +231,33 @@
<version>${net.coobird.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>${spring-boot.version}</version>
</dependency>

<!-- 添加GeoTools依赖 -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>${geotools.version}</version>
</dependency>

<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-swing</artifactId>
<version>${geotools.version}</version>
</dependency>

<!-- wkt转geojson -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>${geotools.version}</version>
</dependency>



<!-- 定时任务-->
@@ -312,6 +340,17 @@
<enabled>true</enabled>
</releases>
</repository>
<repository>
<id>osgeo</id>
<name>OSGeo Release Repository</name>
<url>https://repo.osgeo.org/repository/release/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>

<pluginRepositories>


+ 5
- 0
ruoyi-admin/pom.xml Ver ficheiro

@@ -67,6 +67,11 @@
<artifactId>ruoyi-business</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

</dependencies>

<build>


+ 37
- 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/business/TTaskImportController.java Ver ficheiro

@@ -14,6 +14,7 @@ import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.pdf.PdfUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.translation.TranslateUtils;
import com.ruoyi.geo.service.GeoImportHandlerService;
import com.ruoyi.system.service.ISysDeptService;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
@@ -38,7 +39,9 @@ public class TTaskImportController extends BaseController
private ITTaskImportService tTaskImportService;

@Autowired
private ISysDeptService deptService;
private ISysDeptService deptService;
@Autowired
private GeoImportHandlerService importHandlerService;

/**
* 查询导入任务列表
@@ -202,4 +205,37 @@ public class TTaskImportController extends BaseController

PdfUtils.initPdf(response, pdf);
}

/**
* 开始导入任务
*/
@PreAuthorize("@ss.hasPermi('business:import:do')")
@Log(title = "开始导入任务", businessType = BusinessType.UPDATE)
@PostMapping("/start/{taskId}")
public AjaxResult start(@PathVariable Long taskId)
{
return AjaxResult.success(importHandlerService.StartTask(taskId));
}

/**
* 获取导入任务日志
*/
@PreAuthorize("@ss.hasPermi('business:import:do')")
@GetMapping("/log/{taskId}")
public AjaxResult log(@PathVariable Long taskId, Integer offset)
{
if(null == offset)
offset = 0;
return AjaxResult.success(importHandlerService.GetImportLog(taskId, offset));
}

/**
* 下载导入任务日志
*/
@PreAuthorize("@ss.hasPermi('business:import:do')")
@GetMapping("/downloadLog/{taskId}")
public void downloadLog(@PathVariable Long taskId, HttpServletResponse response)
{
importHandlerService.DownloadLog(taskId, response);
}
}

+ 7
- 1
ruoyi-admin/src/main/resources/application.yml Ver ficheiro

@@ -66,7 +66,7 @@ spring:
devtools:
restart:
# 热部署开关
enabled: true
enabled: false
# redis 配置
redis:
# 地址
@@ -133,3 +133,9 @@ xss:
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*

importTask:
# 是否启动时执行等待中的任务
startOnBoot: false
# 下次建议读取日志的间隔(毫秒)
logNextPoll: 2000

+ 53
- 0
ruoyi-admin/src/test/java/GeoTest.java Ver ficheiro

@@ -0,0 +1,53 @@
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.RuoYiApplication;
import com.ruoyi.common.geo.GeoParser;
import com.ruoyi.geo.service.GeoImportHandlerService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Slf4j
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = RuoYiApplication.class)
public final class GeoTest
{
@Resource
private GeoImportHandlerService service;

@Test
public void test()
{
service.StartTask(4L);
//new Scanner(System.in).next();
ThreadUtil.sleep(5000);
}

public static void main(String[] args)
{
String PATH;
PATH = "D:/m/胜利村_shp_3857/cjqy.shp"; // cjqy
PATH = "D:/m/胜利村_shp_3857/dk.shp"; // dk
PATH = "D:/m/胜利村_shp_3857/zyhycg.shp"; // zyhycg
PATH = "D:/m/胜利村_shp_3857/jtzy.shp"; // jtzy
try(GeoParser geo = new GeoParser())
{
geo.Open(PATH, "UTF-8");
System.err.println(geo.GetTypeNames());
geo.SetSource(0);
List<Map<String, Object>> cjqies = geo.GetMapList();
//List<GeoCJQY> cjqies = geo.GetList(GeoCJQY.class);
//List<GeoJTZY> cjqies = geo.GetList(GeoJTZY.class);
//List<GeoZYHYCG> cjqies = geo.GetList(GeoZYHYCG.class);
//List<GeoDK> cjqies = geo.GetList(GeoDK.class);

System.err.println(JSON.toJSONString(cjqies));
}
}
}

+ 25
- 0
ruoyi-business/src/main/java/com/ruoyi/business/constants/TaskEnums.java Ver ficheiro

@@ -0,0 +1,25 @@
package com.ruoyi.business.constants;

public final class TaskEnums
{
public static final class TaskStatus
{
public static final String ST_READY = "0"; // 已准备
public static final String ST_WAIT = "1"; // 排队中
public static final String ST_RUNNING = "2"; // 运行中
public static final String ST_FINISH = "3"; // 已完成
public static final String ST_FAIL = "4"; // 失败
public static final String ST_TERMINATED = "5"; // 被终止

private TaskStatus() {}
}
public static final class ImportType
{
public static final String IT_OVERRIDE = "1"; // 覆盖导入
public static final String IT_APPEND = "2"; // 增量导入

private ImportType() {}
}

private TaskEnums() {}
}

+ 2
- 0
ruoyi-business/src/main/java/com/ruoyi/business/mapper/TGisCjqyMapper.java Ver ficheiro

@@ -74,4 +74,6 @@ public interface TGisCjqyMapper
* @return 结果
*/
public int deleteTGisCjqyByFids(Long[] fids);

public int deleteByCode(String importCode);
}

+ 3
- 0
ruoyi-business/src/main/java/com/ruoyi/business/mapper/TTaskImportMapper.java Ver ficheiro

@@ -74,4 +74,7 @@ public interface TTaskImportMapper
* @return 结果
*/
public int deleteTTaskImportByIds(Long[] ids);

public int terminateRunningTask();
public TTaskImport getForUpdate(Long id);
}

+ 22
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/config/GeoImportTaskConfig.java Ver ficheiro

@@ -0,0 +1,22 @@
package com.ruoyi.geo.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "import-task")
public class GeoImportTaskConfig
{
public static boolean startOnBoot = false; // 是否启动时执行等待中的任务
public static long logNextPoll = 2000; // 下次建议读取日志的间隔(毫秒)

public void setStartOnBoot(boolean startOnBoot)
{
GeoImportTaskConfig.startOnBoot = startOnBoot;
}

public void setLogNextPoll(long logNextPoll)
{
GeoImportTaskConfig.logNextPoll = logNextPoll;
}
}

+ 11
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/constants/GeoShpType.java Ver ficheiro

@@ -0,0 +1,11 @@
package com.ruoyi.geo.constants;

public final class GeoShpType
{
public static final String CJQY = "cjqy";
public static final String JTZY = "jtzy";
public static final String ZYHYCG = "zyhycg";
public static final String DK = "dk";

private GeoShpType() {}
}

+ 72
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/constants/GeoSysDir.java Ver ficheiro

@@ -0,0 +1,72 @@
package com.ruoyi.geo.constants;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.StringUtils;

public final class GeoSysDir
{
// 导入日志路径
public static final String LOG = "/log";
// 导入zip临时解压路径
public static final String ZIP_EXTRACT_TEMP = "/unzip";

public static String GetDir(String path)
{
if(StringUtils.isEmpty(path))
path = "";
else if(!path.startsWith("/"))
path = "/" + path;
String str = "";
if(!path.startsWith(RuoYiConfig.getProfile()))
str += RuoYiConfig.getProfile();
str += path;
return str;
}

public static String CacheDir(String dir)
{
if(null == dir)
dir = "";
return GetDir("/cache" + dir);
}

public static String ImportDir(String dir)
{
if(null == dir)
dir = "";
return GetDir("/import" + dir);
}

public static String ExportDir(String dir)
{
if(null == dir)
dir = "";
return GetDir("/export" + dir);
}

public static String Desensitized(String path)
{
if(StringUtils.isEmpty(path))
return path;

String fpath = path.replaceAll("\\\\", "/");
String fprofile = RuoYiConfig.getProfile().replaceAll("\\\\", "/");
if(!fpath.startsWith(fprofile))
return path;
return "<profile directory>" + path.substring(RuoYiConfig.getProfile().length());
}

public static String DesensitizedNormalized(String path)
{
if(StringUtils.isEmpty(path))
return path;

String fpath = path.replaceAll("\\\\", "/");
String fprofile = RuoYiConfig.getProfile().replaceAll("\\\\", "/");
if(!fpath.startsWith(fprofile))
return path;
return "<profile directory>" + fpath.substring(fprofile.length());
}

private GeoSysDir() {}
}

+ 149
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoCjqyTask.java Ver ficheiro

@@ -0,0 +1,149 @@
package com.ruoyi.geo.framework;

import cn.hutool.core.collection.ListUtil;
import com.ruoyi.business.domain.TGisCjqy;
import com.ruoyi.business.mapper.TGisCjqyMapper;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.geo.service.GeoImportHandlerService;
import com.ruoyi.geo.structs.GeoCJQY;
import static com.ruoyi.business.constants.TaskEnums.ImportType;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class GeoCjqyTask implements GeoDBTaskInterface
{
private final static String TYPE_NAME = "村级区域";

private final GeoImportTask importTask;
private List<GeoCJQY> list;

public GeoCjqyTask(GeoImportTask importTask)
{
this.importTask = importTask;
}

public int LoadDataList()
{
list = importTask.parser.GetList(GeoCJQY.class);
importTask.logFile.WriteLine(TYPE_NAME + "shp读取数据条数: " + list.size());

return list.size();
}

public void CheckData()
{
boolean hasEmpty = list.stream().anyMatch((x) -> StringUtils.isEmpty(x.CJQYDM));
if(hasEmpty)
{
importTask.logFile.ErrorLine("shp文件支持源中的行政区划代码缺失");
return;
}

List<String> collect = list.stream().map((x) -> x.CJQYDM).distinct().collect(Collectors.toList());

for(String importCode : collect)
{
SysDept dept = importTask.importDeptMap.get(importCode);
if(null == dept)
{
importTask.logFile.ErrorLine("shp文件支持源中的行政区划代码在系统不存在: " + importCode);
return;
}
if(!dept.getOrgCode().startsWith(importTask.taskImport.getOrgCode()))
{
importTask.logFile.ErrorLine(TYPE_NAME + "shp文件支持源中的行政区划代码与系统不匹配: 文件({}) != 系统({})", dept.getOrgCode(), importTask.taskImport.getOrgCode());
}
}
}

private List<TGisCjqy> LoadDatabase(String qydm)
{
TGisCjqy cond = new TGisCjqy();
cond.setCjqydm(qydm);
List<TGisCjqy> cjqies = GeoImportHandlerService.GisCjqyMapper().selectTGisCjqyList(cond);
importTask.logFile.WriteLine(TYPE_NAME + "读取系统已存在的条数: 区划代码={}, 条数={}", qydm, cjqies.size());
return cjqies;
}

private TGisCjqy ConvertData(GeoCJQY src, TGisCjqy dst, SysDept dept)
{
if(null == dst)
dst = new TGisCjqy();
dst.setTheGeom(src.the_geom);
dst.setImportCode(dept.getImportCode());
dst.setCjqydm(src.CJQYDM);
dst.setBsm(src.BSM.longValue());
dst.setCjqymc(src.CJQYMC);
dst.setYsdm(src.YSDM);
return dst;
}

private int CleanDatabase(String importCode)
{
if(ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType()))
{
importTask.logFile.WriteLine(TYPE_NAME + "覆盖导入, 需清空现有数据, 然后再插入, 区划代码={}", importCode);
int ret = GeoImportHandlerService.GisCjqyMapper().deleteByCode(importCode);
importTask.logFile.WriteLine(TYPE_NAME + "清空现有数据: {}, 区划代码={}", ret, importCode);
return ret;
}
else
{
importTask.logFile.WriteLine(TYPE_NAME + "增量导入, 无需清空现有数据, 仅执行插入或更新, 区划代码={}", importCode);
return -1;
}
}

private int WriteData(List<TGisCjqy> insertList, List<TGisCjqy> updateList, SysDept dept)
{
TGisCjqyMapper gisCjqyMapper = GeoImportHandlerService.GisCjqyMapper();
int i = ListUtil.split(insertList, 50).stream().map(gisCjqyMapper::insertTGisCjqyBatch).reduce(0, Integer::sum);
importTask.logFile.WriteLine(TYPE_NAME + "新增数据: 区划代码={}, 条数={}", dept.getDeptName(), i);
int u = ListUtil.split(updateList, 50).stream().map(gisCjqyMapper::updateTGisCjqyBatch).reduce(0, Integer::sum);
importTask.logFile.WriteLine(TYPE_NAME + "更新数据: 区划代码={}, 条数={}", dept.getDeptName(), u);
return i + u;
}

private int SaveDeptData(SysDept dept, List<GeoCJQY> datas)
{
importTask.logFile.WriteLine(TYPE_NAME + "开始处理数据: 区划代码={}, 条数={}", dept.getDeptName(), datas.size());
List<TGisCjqy> databases = LoadDatabase(dept.getImportCode());
Map<String, TGisCjqy> exists = databases.stream().collect(Collectors.toMap(TGisCjqy::getCjqydm, x->x));

List<TGisCjqy> insertList = new ArrayList<>();
List<TGisCjqy> updateList = new ArrayList<>();

for(GeoCJQY data : datas)
{
TGisCjqy db = exists.get(data.CJQYDM);
boolean has = null == db;
db = ConvertData(data, db, dept);
if(has)
insertList.add(db);
else
updateList.add(db);
}

CleanDatabase(dept.getImportCode());
int ret = WriteData(insertList, updateList, dept);
importTask.logFile.WriteLine(TYPE_NAME + "总写入数据: 区划代码={}, 条数={}", dept.getDeptName(), ret);
return ret;
}

public int SaveData()
{
int ret = 0;
Map<String, List<GeoCJQY>> group = list.stream().collect(Collectors.groupingBy((x) -> x.CJQYDM));
importTask.logFile.WriteLine(TYPE_NAME + "shp数据: 区划代码类型数={}", group.size());
for(String dm : group.keySet())
{
SysDept dept = importTask.importDeptMap.get(dm);
ret = SaveDeptData(dept, group.get(dm));
}
return ret;
}
}

+ 8
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoDBTaskInterface.java Ver ficheiro

@@ -0,0 +1,8 @@
package com.ruoyi.geo.framework;

public interface GeoDBTaskInterface
{
public int LoadDataList();
public void CheckData();
public int SaveData();
}

+ 14
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoException.java Ver ficheiro

@@ -0,0 +1,14 @@
package com.ruoyi.geo.framework;

public class GeoException extends RuntimeException
{
public GeoException(String msg)
{
super(msg);
}

public GeoException(Throwable e)
{
super(e);
}
}

+ 46
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoFileSystem.java Ver ficheiro

@@ -0,0 +1,46 @@
package com.ruoyi.geo.framework;

import cn.hutool.core.io.FileUtil;
import com.ruoyi.common.utils.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public final class GeoFileSystem
{
public static List<String> FindFiles(File dir, String suffix)
{
return FindFiles_r(new ArrayList<>(), dir, suffix);
}

public static List<String> FindFiles_r(List<String> list, File dir, String suffix)
{
File[] files;
if(StringUtils.isEmpty(suffix))
files = dir.listFiles();
else
{
String ext = suffix.toLowerCase();
files = dir.listFiles((d, f) -> {
if(FileUtil.isDirectory(d.getAbsolutePath() + File.separatorChar + f))
return true;
return f.toLowerCase().endsWith(ext);
});
}

if(null != files)
{
for(File file : files)
{
if(file.isDirectory())
FindFiles_r(list, file, suffix);
else
list.add(file.getAbsolutePath());
}
}
return list;
}

private GeoFileSystem() {}
}

+ 293
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoImportTask.java Ver ficheiro

@@ -0,0 +1,293 @@
package com.ruoyi.geo.framework;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.ruoyi.business.domain.TTaskImport;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.geo.GeoParser;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.sql.DB;
import com.ruoyi.geo.constants.GeoShpType;
import com.ruoyi.geo.constants.GeoSysDir;
import com.ruoyi.geo.service.GeoImportHandlerService;
import com.ruoyi.system.mapper.SysDeptMapper;
import lombok.extern.slf4j.Slf4j;
import static com.ruoyi.business.constants.TaskEnums.TaskStatus;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class GeoImportTask implements Runnable
{
private final Long taskId;
TTaskImport taskImport;
GeoTaskLog logFile;
GeoParser parser;
Map<String, SysDept> importDeptMap;
private Map<String, SysDept> sysDeptMap;
private List<String> shpFiles;
private List<String> typeNames;
private String shpPath;
private String type;
String username;
Date now;

private GeoDBTaskInterface task;

public GeoImportTask(Long taskId)
{
this.taskId = taskId;
}

public void Init()
{
now = new Date();
username = "admin"; //SecurityUtils.getUsername();
String path = LogPath();
log.info("任务{}日志文件: {}", taskId, path);
logFile = new GeoTaskLog(path);
logFile.Open();
logFile.WriteLine("任务初始化: {} - {}", taskId, DateUtil.format(now, "yyyy-MM-dd HH:mm:ss.SSS"));
}

public void Shutdown()
{
CleanTempFiles();

logFile.WriteLine("任务结束: {} - {}", taskId, DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
if(null != logFile)
{
logFile.close();
}
log.info("任务{}日志文件: {}", taskId, GeoSysDir.DesensitizedNormalized(LogPath()));
}

private String UnzipCachePath()
{
return GeoSysDir.CacheDir(GeoSysDir.ZIP_EXTRACT_TEMP + "/" + taskId);
}

public String LogPath()
{
return GeoSysDir.ImportDir(GeoSysDir.LOG) + "/" + taskId + ".log";
}

private void ExtractZip()
{
// 先清空源临时解压文件
CleanTempFiles();

File file = new File(RuoYiConfig.getProfile() + "/" + taskImport.getFileUrl());
logFile.WriteLine("正在打开zip文件: " + GeoSysDir.DesensitizedNormalized(file.getAbsolutePath()));
if(!file.isFile())
{
logFile.ErrorLine("zip文件不存在: " + GeoSysDir.DesensitizedNormalized(file.getAbsolutePath()));
}

String toDir = UnzipCachePath();
File dir = ZipUtil.unzip(file, new File(toDir));
shpFiles = GeoFileSystem.FindFiles(dir, ".shp");
logFile.WriteLine("zip文件中发现shp文件: " + shpFiles.size());
if(shpFiles.isEmpty())
{
logFile.ErrorLine("zip文件中未找到shp文件: " + GeoSysDir.DesensitizedNormalized(file.getAbsolutePath()));
}

int i = 0;
for(String shpFile : shpFiles)
{
logFile.WriteLine("{}: {}", ++i, GeoSysDir.DesensitizedNormalized(shpFile));
}
}

private void CleanTempFiles()
{
String toDir = UnzipCachePath();
logFile.WriteLine("清理临时文件: " + GeoSysDir.DesensitizedNormalized(toDir));
FileUtil.del(toDir);
}

private void ParseShp()
{
if(null == parser)
parser = new GeoParser();

parser.close();

if(!parser.Open(shpPath, "UTF-8"))
{
logFile.ErrorLine("打开shp文件错误: " + shpPath);
}

typeNames = parser.GetTypeNames();

if(CollectionUtil.isEmpty(typeNames))
{
logFile.ErrorLine("shp文件支持源未读取到任何数据类型: " + shpPath);
}
}

private boolean LoadDataList()
{
if(!parser.SetSource(type))
{
logFile.ErrorLine("shp文件未找到支持源: " + type);
return false;
}

int num = task.LoadDataList();
if(num == 0)
{
logFile.WriteLine("shp文件支持源未读取到数据: " + type);
return false;
}

task.CheckData();
return true;
}

private void LoadDept()
{
SysDept cond = new SysDept();
SysDeptMapper deptMapper = SpringUtils.getBean(SysDeptMapper.class);
List<SysDept> sysDepts = deptMapper.selectDeptList(cond);
importDeptMap = sysDepts.stream().collect(Collectors.toMap(SysDept::getImportCode, x -> x));
sysDeptMap = sysDepts.stream().collect(Collectors.toMap(SysDept::getOrgCode, x -> x));
}

private void LoadTask()
{
TTaskImport task = GeoImportHandlerService.TaskImportMapper().getForUpdate(taskId);
if(null == task)
{
logFile.ErrorLine("任务配置不存在: " + taskId);
return;
}
if(!TaskStatus.ST_WAIT.equals(task.getTaskStatus()))
{
logFile.ErrorLine("任务非等待状态: " + taskId);
return;
}
taskImport = task;
}

private void SaveTask(String st)
{
if(null != taskImport)
{
taskImport.setTaskStatus(st);
GeoImportHandlerService.TaskImportMapper().updateTTaskImport(taskImport);
}
}

private void HandleShpFiles()
{
for(String shpFile : shpFiles)
{
shpPath = shpFile;
HandleShpFile();
}
}

private void HandleShpFile()
{
// 1. 读取当前shp文件中的所有类型
ParseShp();
for(String typeName : typeNames)
{
type = typeName;
// 2. 分发任务
DispatchTask();
}
}

private void DispatchTask()
{
// 1. 选择任务类型
switch(type.toLowerCase())
{
case GeoShpType.CJQY:
task = new GeoCjqyTask(this);
break;
case GeoShpType.JTZY:
task = new GeoJtzyTask(this);
break;
case GeoShpType.ZYHYCG:
task = new GeoZyhycgTask(this);
break;
default:
logFile.WriteLine("数据类型不支持: " + type);
return;
}
// 2. 处理导入任务
DoTask();
}

private void DoTask()
{
// 1. 读取数据列表
if(!LoadDataList())
return;

// 2. 保存数据列表
task.SaveData();
}

private void Handle()
{
// 0. 初始化任务: 打开日志系统
Init();

// 1. 加载任务配置, 并检查
LoadTask();

// 2. 读取文件, 解压文件到工作目录
ExtractZip();

// 3. 加载部门数据
LoadDept();

// 4. 依次处理所有shp文件
HandleShpFiles();
}

@Override
public void run()
{
Object handle = null;
try
{
handle = DB.BeginTransaction();

Handle();

// 更改任务状态为已完成
SaveTask(TaskStatus.ST_FINISH);
}
catch(Exception e)
{
e.printStackTrace();
logFile.WriteLine(ExceptionUtil.getExceptionMessage(e));
SaveTask(TaskStatus.ST_FAIL);
}
finally
{
DB.EndTransaction(handle);
// -1: 终止任务, 关闭日志系统
Shutdown();
}
}

public Long GetTaskId()
{
return taskId;
}
}

+ 181
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoJtzyTask.java Ver ficheiro

@@ -0,0 +1,181 @@
package com.ruoyi.geo.framework;

import cn.hutool.core.collection.ListUtil;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.geo.service.GeoImportHandlerService;
import com.ruoyi.geo.structs.GeoJTZY;
import com.ruoyi.resource.domain.TResourceLand;
import com.ruoyi.resource.mapper.TResourceLandMapper;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.ruoyi.business.constants.TaskEnums.ImportType;

public class GeoJtzyTask implements GeoDBTaskInterface
{
private final static String TYPE_NAME = "地块属性";

private final GeoImportTask importTask;
private List<GeoJTZY> list;

public GeoJtzyTask(GeoImportTask importTask)
{
this.importTask = importTask;
}

public int LoadDataList()
{
list = importTask.parser.GetList(GeoJTZY.class);
importTask.logFile.WriteLine(TYPE_NAME + "shp读取数据条数: " + list.size());

return list.size();
}

public void CheckData()
{
boolean hasEmpty = list.stream().anyMatch((x) -> (StringUtils.isEmpty(x.DKBM) && StringUtils.isEmpty(x.QSDWDM)) || (x.DKBM.length() < 12 && x.QSDWDM.length() < 12));
if(hasEmpty)
{
importTask.logFile.ErrorLine("shp文件支持源中的行政区划代码缺失或不完整");
return;
}

List<String> collect = list.stream().map(GeoJTZY::Code).distinct().collect(Collectors.toList());

for(String importCode : collect)
{
SysDept dept = importTask.importDeptMap.get(importCode);
if(null == dept)
{
importTask.logFile.WriteLine("shp文件支持源中的行政区划代码在系统不存在: " + importCode);
continue;
}
if(!dept.getOrgCode().startsWith(importTask.taskImport.getOrgCode()))
{
importTask.logFile.ErrorLine(TYPE_NAME + "shp文件支持源中的行政区划代码与系统不匹配: 文件({}) != 系统({})", dept.getOrgCode(), importTask.taskImport.getOrgCode());
}
}
}

private List<TResourceLand> LoadDatabase(String qydm)
{
TResourceLand cond = new TResourceLand();
cond.setImportCode(qydm);
List<TResourceLand> cjqies = GeoImportHandlerService.ResourceLandMapper().selectTResourceLandList(cond);
importTask.logFile.WriteLine(TYPE_NAME + "读取系统已存在的条数: 区划代码={}, 条数={}", qydm, cjqies.size());
return cjqies;
}

private TResourceLand ConvertData(GeoJTZY src, TResourceLand dst, SysDept dept)
{
boolean notExists = null == dst;
if(notExists)
dst = new TResourceLand();
dst.setTheGeom(src.the_geom);
dst.setImportCode(dept.getImportCode());
dst.setBsm(src.BSM);
dst.setYsdm(src.YSDM);
dst.setDkbm(src.DKBM);
dst.setDkmc(src.DKMC);
dst.setSyqxz(src.SYQXZ);
dst.setDklb(src.DKLB);
dst.setDldj(src.DLDJ);
dst.setTdyt(src.TDYT);
dst.setSfjbnt(src.SFJBNT);
dst.setDkdz(src.DKDZ);
dst.setDkxz(src.DKXZ);
dst.setDknz(src.DKNZ);
dst.setDkbz(src.DKBZ);
dst.setZjrxm(src.ZJRXM);
dst.setDkbzxx(src.DKBZXX);
dst.setTxmj(src.TXMJ);
dst.setQsdwdm(src.QSDWDM);
dst.setQsdwmc(src.QSDWMC);
dst.setSfzwd(src.SFZWD);
dst.setScmjm(src.SCMJM);
dst.setDeptName(dept.getDeptName());
if(notExists)
{
dst.setSurveyStatus("1");
dst.setCreateBy(importTask.username);
dst.setCreateTime(importTask.now);
}
else
{
dst.setUpdateBy(importTask.username);
dst.setUpdateTime(importTask.now);
}
return dst;
}

private int CleanDatabase(String importCode)
{
if(ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType()))
{
importTask.logFile.WriteLine(TYPE_NAME + "覆盖导入, 需清空现有数据, 然后再插入, 区划代码={}", importCode);
int ret = GeoImportHandlerService.ResourceLandMapper().deleteByCode(importCode);
importTask.logFile.WriteLine(TYPE_NAME + "清空现有数据: {}, 区划代码={}", ret, importCode);
return ret;
}
else
{
importTask.logFile.WriteLine(TYPE_NAME + "增量导入, 无需清空现有数据, 仅执行插入或更新, 区划代码={}", importCode);
return -1;
}
}

private int WriteData(List<TResourceLand> insertList, List<TResourceLand> updateList, SysDept dept)
{
TResourceLandMapper gisCjqyMapper = GeoImportHandlerService.ResourceLandMapper();
int i = ListUtil.split(insertList, 30).stream().map(gisCjqyMapper::insertTResourceLandBatch).reduce(0, Integer::sum);
importTask.logFile.WriteLine(TYPE_NAME + "新增数据: 区划代码={}, 条数={}", dept.getDeptName(), i);
int u = ListUtil.split(updateList, 1).stream().map(gisCjqyMapper::updateTResourceLandBatch).reduce(0, Integer::sum);
importTask.logFile.WriteLine(TYPE_NAME + "更新数据: 区划代码={}, 条数={}", dept.getDeptName(), u);
return i + u;
}

private int SaveDeptData(SysDept dept, List<GeoJTZY> datas)
{
importTask.logFile.WriteLine(TYPE_NAME + "开始处理数据: 区划代码={}, 条数={}", dept.getDeptName(), datas.size());
List<TResourceLand> databases = LoadDatabase(dept.getImportCode());
Map<String, TResourceLand> exists = databases.stream().collect(Collectors.toMap(TResourceLand::getDkbm, x->x));

List<TResourceLand> insertList = new ArrayList<>();
List<TResourceLand> updateList = new ArrayList<>();

for(GeoJTZY data : datas)
{
TResourceLand db = exists.get(data.DKBM);
boolean notExists = null == db;
db = ConvertData(data, db, dept);
if(notExists)
insertList.add(db);
else
updateList.add(db);
}

CleanDatabase(dept.getImportCode());
int ret = WriteData(insertList, updateList, dept);
importTask.logFile.WriteLine(TYPE_NAME + "总写入数据: 区划代码={}, 条数={}", dept.getDeptName(), ret);
return ret;
}

public int SaveData()
{
int ret = 0;
Map<String, List<GeoJTZY>> group = list.stream().collect(Collectors.groupingBy(GeoJTZY::Code));
importTask.logFile.WriteLine(TYPE_NAME + "shp数据: 区划代码类型数={}", group.size());
for(String dm : group.keySet())
{
SysDept dept = importTask.importDeptMap.get(dm);
if(null == dept)
continue;
ret = SaveDeptData(dept, group.get(dm));
}
return ret;
}
}

+ 174
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoTaskLog.java Ver ficheiro

@@ -0,0 +1,174 @@
package com.ruoyi.geo.framework;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

@Slf4j
public class GeoTaskLog implements Closeable
{
private BufferedWriter writer;
private String path;
private boolean autoFlush;

public GeoTaskLog(String path)
{
this(path, true);
}

public GeoTaskLog(String path, boolean autoFlush)
{
this.path = path;
this.autoFlush = autoFlush;
}

public boolean IsOpened()
{
return null != writer;
}

public boolean Open()
{
Assert.isNull(writer, "日志文件已经打开");

File file = CreateFile();
if(null == file)
return false;

try
{
FileWriter fos = new FileWriter(file);
writer = new BufferedWriter(fos);
log.info("打开日志文件: " + path);
return true;
}
catch(Exception e)
{
e.printStackTrace();
return false;
}
}

@Override
public void close()
{
if(null != writer)
{
try
{
log.info("关闭日志文件: " + path);
writer.flush();
writer.close();
writer = null;
}
catch(IOException e)
{
throw new RuntimeException(e);
}
}
}

private void AfterWrite()
{
if(autoFlush)
{
try
{
writer.flush();
}
catch(IOException e)
{
throw new RuntimeException(e);
}
}
}

private void CheckWriter()
{
Assert.notNull(writer, "文件未打开");
}

public void Error(String str, Object...args)
{
String text = StrUtil.format(str, args);
Write(text);
throw new GeoException(text);
}

public void ErrorLine(String str, Object...args)
{
String text = StrUtil.format(str, args);
WriteLine(text);
throw new GeoException(text);
}

public void Write(String str, Object...args)
{
String text = StrUtil.format(str, args);
log.info(text);

//ThreadUtil.sleep(5000);

CheckWriter();

try
{
writer.write(text);
AfterWrite();
}
catch(IOException e)
{
throw new RuntimeException(e);
}
}

public String GetString()
{
File file = new File(path);
if(!file.isFile())
return null;
return FileUtil.readUtf8String(file);
}

public void WriteLine(String str, Object...args)
{
Write(str, args);
try
{
writer.newLine();
AfterWrite();
}
catch(IOException e)
{
throw new RuntimeException(e);
}
}

private File CreateFile()
{
File file = new File(path);
if(file.exists())
{
log.error("日志文件已存在: " + path);
log.warn("覆盖日志文件: " + path);
return file;
}

FileUtil.mkParentDirs(path);

return file;
}

public String Path()
{
return path;
}
}

+ 261
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoTaskQueue.java Ver ficheiro

@@ -0,0 +1,261 @@
package com.ruoyi.geo.framework;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;

/**
* 队列式任务线程
*/
@Slf4j
public class GeoTaskQueue implements Runnable
{
private static final int ST_DILE = 0;
private static final int ST_READY = 1;
private static final int ST_RUNNING = 2;
private static final int ST_WORKING = 3;
private static final int ST_WAITING = 4;
private static final int ST_END = 5;
private static final int ST_TERMINATED = 6;

private volatile Thread thread;
private final List<Runnable> queue = new LinkedList<>();
private final AtomicInteger state = new AtomicInteger(ST_DILE);
private final Object lock = new Object();
private volatile boolean reqQuit = false;
private final boolean quitOnNoTask;
private Runnable currentTask = null;
// 计数器
private volatile int c_loop = 0;
private volatile int c_wait = 0;
private volatile int c_work = 0;
private volatile int c_error = 0;
private volatile int c_run = 0;

public GeoTaskQueue(boolean quitOnNoTask) {
this.quitOnNoTask = quitOnNoTask;
}

@Override
public void run()
{
Runnable task;

log.info("[任务队列线程]: {}开始执行 -> {}", Thread.currentThread().getName(), Thread.currentThread().getId());
state.set(ST_RUNNING);
for(;;)
{
c_loop++;
synchronized(this) {
if(reqQuit)
{
reqQuit = false;
boolean hasTask = HasTask();
log.info("[退出任务队列线程]: 退出状态 -> " + (hasTask ? "中断" : "完成"));
state.set(hasTask ? ST_TERMINATED : ST_END);
break;
}
}
task = TakeTask();
if(null == task)
{
if(quitOnNoTask)
{
log.info("[任务队列线程循环]: 当前无任务, 退出");
break;
}
// 如果没有任务, 则暂停线程
synchronized(lock) {
try
{
c_wait++;
log.info("[任务队列线程循环]: 当前无任务, 进入等待状态");
state.set(ST_WAITING);
lock.wait();
log.info("[任务队列线程循环]: 有新任务添加, 继续执行");
}
catch(InterruptedException e)
{
e.printStackTrace();
ThreadUtil.sleep(30000); // 强制等待30秒
}
}
continue;
}
log.info("[任务队列线程循环]: 正在执行任务");
state.set(ST_WORKING);
c_work++;
try
{
task.run();
}
catch(Exception e)
{
c_error++;
e.printStackTrace();
}
synchronized(this) {
currentTask = null;
}
log.info("[任务队列线程循环]: 当前任务执行完成");
state.set(ST_RUNNING);
}
log.info("[任务队列线程循环]: 执行结束");
state.set(IsRunning() ? ST_END : ST_TERMINATED);

synchronized(this) {
thread = null;
}
}

public synchronized int AddTask(Runnable task)
{
queue.add(task);
// 如果有任务, 则唤醒队列循环
synchronized(lock) {
lock.notifyAll();
}
return queue.size();
}

public synchronized int AddTask(List<Runnable> tasks)
{
queue.addAll(tasks);
// 如果有任务, 则唤醒队列循环
synchronized(lock) {
lock.notifyAll();
}
return queue.size();
}

private synchronized Runnable TakeTask()
{
if(queue.isEmpty())
return null;
currentTask = queue.remove(0);
return currentTask;
}

public synchronized boolean HasTask()
{
return !queue.isEmpty();
}

public boolean IsRunning()
{
int st = state.get();
return st == ST_RUNNING || st == ST_WAITING || st == ST_WORKING;
}

public synchronized void RequestQuit()
{
if(!IsRunning())
{
log.warn("[请求结束任务队列线程]: 任务队列线程非运行状态 -> " + state.get());
return;
}
log.info("[请求结束任务队列线程]: 等待当前任务完成后中止");
if(reqQuit)
return;
reqQuit = true;
}

public void Quit()
{
synchronized(this) {
if(null == thread)
return;
}
RequestQuit();
try
{
log.info("[结束任务队列线程]: 等待当前任务完成");
thread.join();
synchronized(this) {
thread = null;
}
}
catch(InterruptedException e)
{
throw new RuntimeException(e);
}
}

private void Reset()
{
log.info("[重置任务队列线程]: 重置状态");
reqQuit = false;
c_loop = 0;
c_wait = 0;
c_work = 0;
c_error = 0;
state.set(ST_DILE);
currentTask = null;
}

public synchronized void StartTask(Runnable task)
{
if(IsRunning())
AddTask(task);
else
{
queue.add(task);
Start();
}
}

public synchronized void StartTask(List<Runnable> task)
{
if(IsRunning())
AddTask(task);
else
{
queue.addAll(task);
Start();
}
}

public synchronized Runnable GetCurrentTask()
{
return currentTask;
}

public synchronized Runnable FindTask(Predicate<Runnable> op)
{
if(queue.isEmpty())
return null;
return queue.stream().filter(op).findFirst().orElse(null);
}

public synchronized void Start()
{
if(null != thread)
{
log.error("[启动任务队列线程]: 上次任务队列线程仍在运行 -> " + thread.getName());
return;
}

int st = state.get();
if(st != ST_DILE && st != ST_END && st != ST_TERMINATED)
{
log.error("[启动任务队列线程]: 任务队列线程非空闲/结束/中止状态 -> " + st);
return;
}
Reset();

if(state.get() != ST_DILE)
{
log.error("[开始任务队列线程]: 任务队列线程非空闲状态");
return;
}
thread = new Thread(this);thread.interrupt();
thread.setName("任务线程_" + c_run++);
state.set(ST_READY);
thread.start();
}
}

+ 179
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/framework/GeoZyhycgTask.java Ver ficheiro

@@ -0,0 +1,179 @@
package com.ruoyi.geo.framework;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.utils.DecimalUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.geo.service.GeoImportHandlerService;
import com.ruoyi.geo.structs.GeoZYHYCG;
import com.ruoyi.resource.domain.TResourceOperation;
import com.ruoyi.resource.mapper.TResourceOperationMapper;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.ruoyi.business.constants.TaskEnums.ImportType;

public class GeoZyhycgTask implements GeoDBTaskInterface
{
private final static String TYPE_NAME = "地块经营";

private final GeoImportTask importTask;
private List<GeoZYHYCG> list;

public GeoZyhycgTask(GeoImportTask importTask)
{
this.importTask = importTask;
}

public int LoadDataList()
{
list = importTask.parser.GetList(GeoZYHYCG.class);
importTask.logFile.WriteLine(TYPE_NAME + "shp读取数据条数: " + list.size());

return list.size();
}

public void CheckData()
{
boolean hasEmpty = list.stream().anyMatch((x) -> StringUtils.isEmpty(x.DKBM) || x.DKBM.length() < 12);
if(hasEmpty)
{
importTask.logFile.ErrorLine("shp文件支持源中的行政区划代码缺失或不完整");
return;
}

List<String> collect = list.stream().map(GeoZYHYCG::Code).distinct().collect(Collectors.toList());

for(String importCode : collect)
{
SysDept dept = importTask.importDeptMap.get(importCode);
if(null == dept)
{
importTask.logFile.WriteLine("shp文件支持源中的行政区划代码在系统不存在: " + importCode);
continue;
}
if(!dept.getOrgCode().startsWith(importTask.taskImport.getOrgCode()))
{
importTask.logFile.ErrorLine(TYPE_NAME + "shp文件支持源中的行政区划代码与系统不匹配: 文件({}) != 系统({})", dept.getOrgCode(), importTask.taskImport.getOrgCode());
}
}
}

private List<TResourceOperation> LoadDatabase(String qydm)
{
TResourceOperation cond = new TResourceOperation();
cond.setImportCode(qydm);
List<TResourceOperation> cjqies = GeoImportHandlerService.ResourceOperationMapper().selectTResourceOperationList(cond);
importTask.logFile.WriteLine(TYPE_NAME + "读取系统已存在的条数: 区划代码={}, 条数={}", qydm, cjqies.size());
return cjqies;
}

private TResourceOperation ConvertData(GeoZYHYCG src, TResourceOperation dst, SysDept dept)
{
boolean notExists = null == dst;
if(notExists)
dst = new TResourceOperation();
dst.setImportCode(dept.getImportCode());
dst.setDkbm(src.DKBM);
dst.setDkmc(src.DKMC);
dst.setDkdz(src.SYQXZ);
dst.setJymj(src.JYMJ);
dst.setJydxlx(src.JYDXLX);
dst.setJydxmc(src.JYDXMC);
dst.setJydxzjlx(src.JYDXZJLX);
dst.setJydxzjhm(src.JYDXZJHM);
dst.setSfqdht(src.SFQDHT);
dst.setJykssj(StrUtil.subPre(src.JYKSSJ, 10));
dst.setJyjssj(StrUtil.subPre(src.JYJSSJ, 10));
dst.setCbje(DecimalUtils.nullToZero(src.CBJE));
dst.setDxje(DecimalUtils.nullToZero(src.DXJE));
dst.setSqje(DecimalUtils.nullToZero(src.SQJE));
dst.setNsy(DecimalUtils.nullToZero(src.NSY));
dst.setBzxx(src.BZXX);
dst.setJyfs(src.JYFS);
dst.setDeptName(dept.getDeptName());
if(notExists)
{
dst.setSurveyStatus("1");
dst.setCreateBy(importTask.username);
dst.setCreateTime(importTask.now);
}
else
{
dst.setUpdateBy(importTask.username);
dst.setUpdateTime(importTask.now);
}
return dst;
}

private int CleanDatabase(String importCode)
{
if(ImportType.IT_OVERRIDE.equals(importTask.taskImport.getImportType()))
{
importTask.logFile.WriteLine(TYPE_NAME + "覆盖导入, 需清空现有数据, 然后再插入, 区划代码={}", importCode);
int ret = GeoImportHandlerService.ResourceOperationMapper().deleteByCode(importCode);
importTask.logFile.WriteLine(TYPE_NAME + "清空现有数据: {}, 区划代码={}", ret, importCode);
return ret;
}
else
{
importTask.logFile.WriteLine(TYPE_NAME + "增量导入, 无需清空现有数据, 仅执行插入或更新, 区划代码={}", importCode);
return -1;
}
}

private int WriteData(List<TResourceOperation> insertList, List<TResourceOperation> updateList, SysDept dept)
{
TResourceOperationMapper gisCjqyMapper = GeoImportHandlerService.ResourceOperationMapper();
int i = ListUtil.split(insertList, 30).stream().map(gisCjqyMapper::insertTResourceOperationBatch).reduce(0, Integer::sum);
importTask.logFile.WriteLine(TYPE_NAME + "新增数据: 区划代码={}, 条数={}", dept.getDeptName(), i);
int u = ListUtil.split(updateList, 1).stream().map(gisCjqyMapper::updateTResourceOperationBatch).reduce(0, Integer::sum);
importTask.logFile.WriteLine(TYPE_NAME + "更新数据: 区划代码={}, 条数={}", dept.getDeptName(), u);
return i + u;
}

private int SaveDeptData(SysDept dept, List<GeoZYHYCG> datas)
{
importTask.logFile.WriteLine(TYPE_NAME + "开始处理数据: 区划代码={}, 条数={}", dept.getDeptName(), datas.size());
List<TResourceOperation> databases = LoadDatabase(dept.getImportCode());
Map<String, TResourceOperation> exists = databases.stream().collect(Collectors.toMap(TResourceOperation::getDkbm, x->x));

List<TResourceOperation> insertList = new ArrayList<>();
List<TResourceOperation> updateList = new ArrayList<>();

for(GeoZYHYCG data : datas)
{
TResourceOperation db = exists.get(data.DKBM);
boolean notExists = null == db;
db = ConvertData(data, db, dept);
if(notExists)
insertList.add(db);
else
updateList.add(db);
}

CleanDatabase(dept.getImportCode());
int ret = WriteData(insertList, updateList, dept);
importTask.logFile.WriteLine(TYPE_NAME + "总写入数据: 区划代码={}, 条数={}", dept.getDeptName(), ret);
return ret;
}

public int SaveData()
{
int ret = 0;
Map<String, List<GeoZYHYCG>> group = list.stream().collect(Collectors.groupingBy(GeoZYHYCG::Code));
importTask.logFile.WriteLine(TYPE_NAME + "shp数据: 区划代码类型数={}", group.size());
for(String dm : group.keySet())
{
SysDept dept = importTask.importDeptMap.get(dm);
if(null == dept)
continue;
ret = SaveDeptData(dept, group.get(dm));
}
return ret;
}
}

+ 13
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/object/GeoLogInfo.java Ver ficheiro

@@ -0,0 +1,13 @@
package com.ruoyi.geo.object;

import lombok.Data;

@Data
public class GeoLogInfo
{
private Integer length;
private String text;
private Boolean eof;
private String taskStatus;
private Long nextPollDelay;
}

+ 247
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/service/GeoImportHandlerService.java Ver ficheiro

@@ -0,0 +1,247 @@
package com.ruoyi.geo.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.extra.servlet.ServletUtil;
import com.ruoyi.business.domain.TTaskImport;
import com.ruoyi.business.mapper.TGisCjqyMapper;
import com.ruoyi.business.mapper.TTaskImportMapper;
import com.ruoyi.common.utils.sql.DB;
import com.ruoyi.geo.config.GeoImportTaskConfig;
import com.ruoyi.geo.constants.GeoSysDir;
import com.ruoyi.geo.framework.GeoImportTask;
import com.ruoyi.geo.framework.GeoTaskQueue;
import com.ruoyi.geo.object.GeoLogInfo;
import com.ruoyi.resource.mapper.TResourceLandMapper;
import com.ruoyi.resource.mapper.TResourceOperationMapper;
import com.ruoyi.system.mapper.SysDeptMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static com.ruoyi.business.constants.TaskEnums.TaskStatus;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GeoImportHandlerService
{
@Resource
private SysDeptMapper deptMapper;
private static TTaskImportMapper taskImportMapper;
private static TGisCjqyMapper gisCjqyMapper;
private static TResourceLandMapper resourceLandMapper;
private static TResourceOperationMapper resourceOperationMapper;

private GeoTaskQueue taskQueue;

@Autowired
public void setTaskImportMapper(TTaskImportMapper taskImportMapper)
{
GeoImportHandlerService.taskImportMapper = taskImportMapper;
}

@Autowired
public void setGisCjqyMapper(TGisCjqyMapper gisCjqyMapper)
{
GeoImportHandlerService.gisCjqyMapper = gisCjqyMapper;
}

@Autowired
public void setResourceLandMapper(TResourceLandMapper resourceLandMapper)
{
GeoImportHandlerService.resourceLandMapper = resourceLandMapper;
}

@Autowired
public void setResourceOperationMapper(TResourceOperationMapper resourceOperationMapper)
{
GeoImportHandlerService.resourceOperationMapper = resourceOperationMapper;
}

public static TTaskImportMapper TaskImportMapper()
{
return taskImportMapper;
}

public static TGisCjqyMapper GisCjqyMapper()
{
return gisCjqyMapper;
}

public static TResourceLandMapper ResourceLandMapper()
{
return resourceLandMapper;
}

public static TResourceOperationMapper ResourceOperationMapper()
{
return resourceOperationMapper;
}

private synchronized GeoTaskQueue TaskQueue()
{
if(null == taskQueue)
taskQueue = new GeoTaskQueue(true);
return taskQueue;
}

@PostConstruct
public synchronized void Init()
{
SyncTask();
LoadTask();
}

@PreDestroy
public synchronized void Shutdown()
{
if(null != taskQueue)
taskQueue.Quit();
}

private void SyncTask()
{
log.info("更改运行中的任务状态为中止......");
// 更改运行中的任务状态为中止
int i = taskImportMapper.terminateRunningTask();
log.info("已设置运行中的任务状态为中止: " + i);
}

private void LoadTask()
{
if(!GeoImportTaskConfig.startOnBoot)
return;

log.info("拉取排队中的任务......");
TTaskImport cond = new TTaskImport();
cond.setTaskStatus(TaskStatus.ST_WAIT);
List<TTaskImport> taskImports = taskImportMapper.selectTTaskImportList(cond);
log.info("拉取到排队中的任务: " + taskImports.size());
List<Runnable> tasks = taskImports.stream().map((x) -> new GeoImportTask(x.getId())).collect(Collectors.toList());
if(!tasks.isEmpty())
TaskQueue().StartTask(tasks);
}

public GeoLogInfo GetImportLog(Long taskId, int offset)
{
GeoLogInfo info = new GeoLogInfo();
info.setNextPollDelay(GeoImportTaskConfig.logNextPoll);
TTaskImport taskImport = taskImportMapper.selectTTaskImportById(taskId);
Assert.notNull(taskImport, "导入任务不存在");
info.setTaskStatus(taskImport.getTaskStatus());
if(TaskStatus.ST_READY.equals(taskImport.getTaskStatus())/* || TaskStatus.ST_WAIT.equals(taskImport.getTaskStatus())*/)
{
info.setEof(true);
info.setLength(-1);
return info;
}

String path = GeoSysDir.ImportDir(GeoSysDir.LOG) + "/" + taskId + ".log";
if(!FileUtil.isFile(path))
{
info.setEof(true);
info.setLength(-1);
return info;
}

info.setEof(!TaskStatus.ST_RUNNING.equals(info.getTaskStatus()) && !TaskStatus.ST_WAIT.equals(info.getTaskStatus()));
String str = FileUtil.readUtf8String(path);
info.setLength(str.length());
String text;
if(offset >= str.length() - 1)
text = "";
else if(offset > 0)
text = str.substring(offset);
else
text = str;
info.setText(text);

return info;
}

public synchronized int StartTask(Long id)
{
if(null != taskQueue)
{
GeoImportTask task = (GeoImportTask)taskQueue.GetCurrentTask();
Assert.isFalse(null != task && task.GetTaskId().equals(id), "任务正在执行");

boolean exists = null != taskQueue.FindTask((x) -> {
GeoImportTask t = (GeoImportTask) x;
return(t.GetTaskId().equals(id));
});
Assert.isFalse(exists, "任务已在队列中");
}

Object handler = DB.BeginTransaction();
try
{
TTaskImport taskImport = taskImportMapper.getForUpdate(id);
Assert.notNull(taskImport, "任务不存在");
Assert.isTrue(TaskStatus.ST_READY.equals(taskImport.getTaskStatus()), "任务非准备状态");
taskImport.setTaskStatus(TaskStatus.ST_WAIT);
taskImportMapper.updateTTaskImport(taskImport);
DB.CommitTransaction(handler);
}
catch(Exception e)
{
e.printStackTrace();
DB.RollbackTransaction(handler);
return 0;
}
int ret = null != taskQueue && taskQueue.HasTask() ? 1 : 2;
TaskQueue().StartTask(new GeoImportTask(id));
return ret;
}

public void DownloadLog(Long taskId, HttpServletResponse response)
{
String path = GeoSysDir.ImportDir(GeoSysDir.LOG) + "/" + taskId + ".log";
String dlFileName;
try
{
dlFileName = URLEncoder.encode(FileNameUtil.getName(path), "UTF-8");
}
catch(UnsupportedEncodingException e)
{
e.printStackTrace();
dlFileName = "";
}

int bytes = 0;

response.reset();
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", "attachment; filename=\"" + dlFileName + "\"");
response.setContentType("application/octet-stream; charset=UTF-8");

TTaskImport taskImport = taskImportMapper.selectTTaskImportById(taskId);
if(null == taskImport)
{
ServletUtil.write(response, "导入任务不存在", "application/octet-stream; charset=UTF-8");
bytes = "导入任务不存在".getBytes(StandardCharsets.UTF_8).length;
}

File file = new File(path);
if(!file.isFile())
{
ServletUtil.write(response, "日志文件不存在", "application/octet-stream; charset=UTF-8");
bytes = "日志文件不存在".getBytes(StandardCharsets.UTF_8).length;
}

ServletUtil.write(response, file);
response.addHeader("Content-Length", "" + bytes);
}
}

+ 69
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/structs/GeoCJQY.java Ver ficheiro

@@ -0,0 +1,69 @@
package com.ruoyi.geo.structs;

import lombok.ToString;

import java.math.BigDecimal;

@ToString
public final class GeoCJQY
{
/**
* 对象ID
*/
public Long OBJECTID;

/**
* 县级区域代码
*/
public String XJQYDM;

/**
* 边界长度(米)
*/
public BigDecimal Shape_Leng;

/**
* 县级区域名称
*/
public String XJQYMC;

/**
* 村级区域代码
*/
public String CJQYDM;

/**
* 行政区名称
*/
public String XZQMC;

/**
* 区域面积(平方米)
*/
public BigDecimal Shape_Area;

/**
* 村级区域名称
*/
public String CJQYMC;

/**
* 要素代码
*/
public String YSDM;

/**
* 行政区代码
*/
public String XZQDM;

/**
* 标识码
*/
public Integer BSM;

/**
* 几何图形数据(WKT格式)
*/
public String the_geom;
}

+ 90
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/structs/GeoDK.java Ver ficheiro

@@ -0,0 +1,90 @@
package com.ruoyi.geo.structs;

import lombok.ToString;

import java.math.BigDecimal;

@ToString
public final class GeoDK
{
/** 承包人姓名 */
public String ZJRXM;

/** 地块唯一标识符 */
public Long OBJECTID_1;

/** 土地面积(公顷) */
public BigDecimal TXMJ;

/** 是否在一类建设用地区域(1表示是) */
public String SFZWD;

/** 所属行政区划代码(天津市代码200000) */
public String YSDM;

/** 是否基本农田(1表示是) */
public String SFJBNT;

/** 地块唯一标识符 */
public Long OBJECTID;

/** 区划单位代码 */
public String QSDWDM;

/** 剩余使用权年限(10年) */
public BigDecimal SYQXZ;

/** 地块备注信息 */
public String DKBZXX;

/** 地块标识码 */
public Integer BSM;

/** 地块类型(99表示特殊用地) */
public String DKLB;

/** 地块几何坐标(WKT格式) */
public String the_geom;

/** 区划单位名称 */
public String QSDWMC;

/** 地块性质(承包人姓名) */
public String DKXZ;

/** 地块长度(米) */
public BigDecimal Shape_Le_1;

/** 土地用途(1表示耕地) */
public String TDYT;

/** 土地等级(01表示一级地) */
public String DLDJ;

/** 土地来源类型(011表示集体分配) */
public String TDLYLX;

/** 地块周长(米) */
public BigDecimal Shape_Leng;

/** 实测面积(公顷) */
public BigDecimal SCMJM;

/** 地块编码 */
public String DKBM;

/** 地块内作物 */
public String DKNZ;

/** 地块面积(平方米) */
public BigDecimal Shape_Area;

/** 地块名称(孔家) */
public String DKMC;

/** 地块地址(道路) */
public String DKDZ;

/** 地块备注 */
public String DKBZ;
}

+ 107
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/structs/GeoJTZY.java Ver ficheiro

@@ -0,0 +1,107 @@
package com.ruoyi.geo.structs;

import com.ruoyi.common.utils.StringUtils;
import lombok.ToString;

import java.math.BigDecimal;

/**
* 地块信息实体类
*/
@ToString
public final class GeoJTZY
{
/** 地块名称,空字符串表示未命名 */
public String ZJRXM;

/** 地块唯一标识符 */
public Long OBJECTID_1;

/** 地块面积(单位:公顷) */
public BigDecimal TXMJ;

/** 是否在二类建设用地区域(2表示是) */
public String SFZWD;

/** 关联对象ID */
public Long OBJECTID_2;

/** 所属行政区划代码(吉林省代码220000) */
public String YSDM;

/** 是否基本农田(2表示是) */
public String SFJBNT;

/** 地块唯一标识符 */
public Long OBJECTID;

/** 区划单位代码 */
public String QSDWDM;

/** 所有权性质 */
public String SYQXZ;

/** 地块备注信息 */
public String DKBZXX;

/** 地块标识码 */
public Integer BSM;

/** 地块类型 */
public String DKLB;

/** 地块几何坐标(WKT格式) */
public String the_geom;

/** 区划单位名称 */
public String QSDWMC;

/** 地块性质 */
public String DKXZ;

/** 地块长度(米) */
public BigDecimal Shape_Le_1;

/** 地块宽度(米) */
public BigDecimal Shape_Le_2;

/** 土地用途 */
public String TDYT;

/** 土地等级 */
public String DLDJ;

/** 土地来源类型 */
public String TDLYLX;

/** 地块周长(米) */
public BigDecimal Shape_Leng;

/** 实测面积(公顷) */
public BigDecimal SCMJM;

/** 地块编码 */
public String DKBM;

/** 地块内作物 */
public String DKNZ;

/** 地块面积(公顷) */
public BigDecimal Shape_Area;

/** 地块名称(200p平以下删除地块) */
public String DKMC;

/** 地块地址 */
public String DKDZ;

/** 地块备注 */
public String DKBZ;

public String Code()
{
if(StringUtils.isNotEmpty(QSDWDM) && QSDWDM.length() >= 12)
return QSDWDM.substring(0, 12);
return DKBM.substring(0, 12);
}
}

+ 80
- 0
ruoyi-business/src/main/java/com/ruoyi/geo/structs/GeoZYHYCG.java Ver ficheiro

@@ -0,0 +1,80 @@
package com.ruoyi.geo.structs;

import lombok.ToString;

import java.math.BigDecimal;

/**
* 集体用地信息实体类
*/
@ToString
public final class GeoZYHYCG
{
/** 用地类型(1表示集体建设用地) */
public String JYDXLX;

/** 补偿金额 */
public BigDecimal CBJE;

/** 土地面积(公顷) */
public BigDecimal TXMJ;

/** 备注信息(林地未收费) */
public String BZXX;

/** 净用地面积(公顷) */
public BigDecimal JYMJ;

/** 抵押金额 */
public BigDecimal DXJE;

/** 地块唯一标识符 */
public Long OBJECTID;

/** 是否签订合同(2表示已签订) */
public String SFQDHT;

/** 地块周长(米) */
public BigDecimal Shape_Leng;

/** 地块编码 */
public String DKBM;

/** 用地性质证明类型 */
public String JYDXZJLX;

/** 用地单位名称(村集体) */
public String JYDXMC;

/** 用地单位证件号码 */
public String JYDXZJHM;

/** 年收益 */
public BigDecimal NSY;

/** 使用权性质 */
public String SYQXZ;

/** 地块面积(公顷) */
public BigDecimal Shape_Area;

/** 地块名称(胜利村屯里) */
public String DKMC;

/** 地块几何坐标(WKT格式) */
public String the_geom;

/** 经营方式(120表示自主经营) */
public String JYFS;

/** 申请金额 */
public BigDecimal SQJE;

public String JYKSSJ;
public String JYJSSJ;

public String Code()
{
return DKBM.substring(0, 12);
}
}

+ 1
- 0
ruoyi-business/src/main/java/com/ruoyi/resource/mapper/TResourceLandMapper.java Ver ficheiro

@@ -94,5 +94,6 @@ public interface TResourceLandMapper
*/
public TBigDataScreen homepageDownStatistics(Long deptId);

public int deleteByCode(String importCode);

}

+ 2
- 0
ruoyi-business/src/main/java/com/ruoyi/resource/mapper/TResourceOperationMapper.java Ver ficheiro

@@ -77,4 +77,6 @@ public interface TResourceOperationMapper
* @return 结果
*/
public int deleteTResourceOperationByIds(Long[] ids);

public int deleteByCode(String importCode);
}

+ 9
- 5
ruoyi-business/src/main/resources/mapper/business/TGisCjqyMapper.xml Ver ficheiro

@@ -15,7 +15,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>

<sql id="selectTGisCjqyVo">
select cjqydm, cjqymc, bsm, ysdm, the_geom, import_code, fid from t_gis_cjqy
select cjqydm, cjqymc, bsm, ysdm, ST_AsText(the_geom) as the_geom, import_code, fid from t_gis_cjqy
</sql>

<select id="selectTGisCjqyList" parameterType="TGisCjqy" resultMap="TGisCjqyResult">
@@ -47,7 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="cjqymc != null and cjqymc != ''">#{cjqymc},</if>
<if test="bsm != null">#{bsm},</if>
<if test="ysdm != null">#{ysdm},</if>
<if test="theGeom != null">#{theGeom},</if>
<if test="theGeom != null">ST_GEOMFROMTEXT(#{theGeom}),</if>
<if test="importCode != null and importCode != ''">#{importCode},</if>
</trim>
</insert>
@@ -69,7 +69,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item.cjqymc},
#{item.bsm},
#{item.ysdm},
#{item.theGeom},
ST_GEOMFROMTEXT(#{item.theGeom}),
#{item.importCode},
</trim>
</foreach>
@@ -82,7 +82,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="cjqymc != null and cjqymc != ''">cjqymc = #{cjqymc},</if>
<if test="bsm != null">bsm = #{bsm},</if>
<if test="ysdm != null">ysdm = #{ysdm},</if>
<if test="theGeom != null">the_geom = #{theGeom},</if>
<if test="theGeom != null">the_geom = ST_GEOMFROMTEXT(#{theGeom}),</if>
<if test="importCode != null and importCode != ''">import_code = #{importCode},</if>
</trim>
where fid = #{fid}
@@ -97,7 +97,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="item.cjqymc != null and item.cjqymc != ''">cjqymc = #{item.cjqymc},</if>
<if test="item.bsm != null">bsm = #{item.bsm},</if>
<if test="item.ysdm != null">ysdm = #{item.ysdm},</if>
<if test="item.theGeom != null">the_geom = #{item.theGeom},</if>
<if test="item.theGeom != null">the_geom = ST_GEOMFROMTEXT(#{item.theGeom}),</if>
<if test="item.importCode != null and item.importCode != ''">import_code = #{item.importCode},</if>
</set>
where fid = #{item.fid}
@@ -114,4 +114,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{fid}
</foreach>
</delete>

<delete id="deleteByCode" parameterType="String">
delete from t_gis_cjqy where import_code = #{importCode}
</delete>
</mapper>

+ 11
- 0
ruoyi-business/src/main/resources/mapper/business/TTaskImportMapper.xml Ver ficheiro

@@ -161,4 +161,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{id}
</foreach>
</delete>

<update id="terminateRunningTask">
update t_task_import
set task_status = '5'
where task_status = '2'
</update>

<select id="getForUpdate" parameterType="Long" resultMap="TTaskImportResult">
<include refid="selectTTaskImportVo"/>
where id = #{id} FOR UPDATE
</select>
</mapper>

+ 9
- 5
ruoyi-business/src/main/resources/mapper/resource/TResourceLandMapper.xml Ver ficheiro

@@ -49,7 +49,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>

<sql id="selectTResourceLandVo">
select fid, BSM, YSDM, DKBM, DKMC, SYQXZ, DKLB, TDLYLX, DLDJ, TDYT, SFJBNT, DKDZ, DKXZ, DKNZ, DKBZ, DKBZXX, ZJRXM, TXMJ, SCMJM, QSDWDM, QSDWMC, SFZWD, survey_status, import_code, dept_name, create_by, create_time, update_by, update_time from t_resource_land
select fid, BSM, YSDM, DKBM, DKMC, SYQXZ, DKLB, TDLYLX, DLDJ, TDYT, SFJBNT, DKDZ, DKXZ, DKNZ, DKBZ, DKBZXX, ZJRXM, TXMJ, SCMJM, QSDWDM, QSDWMC, SFZWD, survey_status, import_code, dept_name, ST_AsText(the_geom) as the_geom, create_by, create_time, update_by, update_time from t_resource_land
</sql>

<sql id="selectTResourceLandMap">
@@ -156,7 +156,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="zjrxm != null">#{zjrxm},</if>
<if test="txmj != null">#{txmj},</if>
<if test="scmjm != null">#{scmjm},</if>
<if test="theGeom != null">#{theGeom},</if>
<if test="theGeom != null">ST_GEOMFROMTEXT(#{theGeom}),</if>
<if test="qsdwdm != null">#{qsdwdm},</if>
<if test="qsdwmc != null">#{qsdwmc},</if>
<if test="sfzwd != null">#{sfzwd},</if>
@@ -224,7 +224,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item.zjrxm},
#{item.txmj},
#{item.scmjm},
#{item.theGeom},
ST_GEOMFROMTEXT(#{item.theGeom}),
#{item.qsdwdm},
#{item.qsdwmc},
#{item.sfzwd},
@@ -260,7 +260,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="zjrxm != null">ZJRXM = #{zjrxm},</if>
<if test="txmj != null">TXMJ = #{txmj},</if>
<if test="scmjm != null">SCMJM = #{scmjm},</if>
<if test="theGeom != null">the_geom = #{theGeom},</if>
<if test="theGeom != null">the_geom = ST_GEOMFROMTEXT(#{theGeom}),</if>
<if test="qsdwdm != null">QSDWDM = #{qsdwdm},</if>
<if test="qsdwmc != null">QSDWMC = #{qsdwmc},</if>
<if test="sfzwd != null">SFZWD = #{sfzwd},</if>
@@ -298,7 +298,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="item.zjrxm != null">ZJRXM = #{item.zjrxm},</if>
<if test="item.txmj != null">TXMJ = #{item.txmj},</if>
<if test="item.scmjm != null">SCMJM = #{item.scmjm},</if>
<if test="item.theGeom != null">the_geom = #{item.theGeom},</if>
<if test="item.theGeom != null">the_geom = ST_GEOMFROMTEXT(#{item.theGeom}),</if>
<if test="item.qsdwdm != null">QSDWDM = #{item.qsdwdm},</if>
<if test="item.qsdwmc != null">QSDWMC = #{item.qsdwmc},</if>
<if test="item.sfzwd != null">SFZWD = #{item.sfzwd},</if>
@@ -367,4 +367,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
LEFT JOIN t_resource_land l ON l.import_code LIKE concat( d.import_code, '%' )
LEFT JOIN t_resource_operation o ON l.DKBM = o.DKBM WHERE d.dept_id = #{deptId}
</select>

<delete id="deleteByCode" parameterType="String">
delete from t_resource_land where import_code = #{importCode}
</delete>
</mapper>

+ 4
- 0
ruoyi-business/src/main/resources/mapper/resource/TResourceOperationMapper.xml Ver ficheiro

@@ -281,4 +281,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{id}
</foreach>
</delete>

<delete id="deleteByCode" parameterType="String">
delete from t_resource_operation where import_code = #{importCode}
</delete>
</mapper>

+ 17
- 0
ruoyi-common/pom.xml Ver ficheiro

@@ -155,6 +155,23 @@
<artifactId>hutool-all</artifactId>
</dependency>

<!-- 添加GeoTools依赖 -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
</dependency>

<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-swing</artifactId>
</dependency>

<!-- wkt转geojson -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
</dependency>


</dependencies>



+ 178
- 0
ruoyi-common/src/main/java/com/ruoyi/common/geo/GeoParser.java Ver ficheiro

@@ -0,0 +1,178 @@
package com.ruoyi.common.geo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Assert;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;

import java.io.Closeable;
import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public final class GeoParser implements Closeable
{
private ShapefileDataStore dataStore;
private SimpleFeatureSource source;
private Map<Integer, String> columnMap;

public GeoParser()
{
}

public void Init()
{
}

@Override
public void close()
{
CloseSource();
if(null != dataStore)
{
dataStore.dispose();
dataStore = null;
}
}

public boolean Open(String path, String charsetName)
{
return Open(new File(path), charsetName);
}

public boolean Open(File file, String charsetName)
{
close();

try {
dataStore = new ShapefileDataStore(file.toURL());
Charset charset = Charset.forName(charsetName);
dataStore.setCharset(charset);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

private void CheckDataStore()
{
Assert.notNull(dataStore, "请先打开");
}

private void CheckSource()
{
Assert.notNull(source, "请先设置数据源");
}

public List<String> GetTypeNames()
{
CheckDataStore();

try {
return Arrays.stream(dataStore.getTypeNames()).collect(Collectors.toList());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

public boolean SetSource(String typeName)
{
CloseSource();
if(null == typeName)
return true;

CheckDataStore();

try {
source = dataStore.getFeatureSource(typeName);
return InitSource();
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

public boolean SetSource(int index)
{
CloseSource();
if(index < 0)
return true;
CheckDataStore();
return SetSource(GetTypeNames().get(index));
}

private void CloseSource()
{
columnMap = null;
source = null;
}

private boolean InitSource()
{
if(null == source)
return false;

try {
if(null == columnMap)
columnMap = new LinkedHashMap<>();
else
columnMap.clear();
SimpleFeatureType schema = source.getSchema();
for(int i = 0; i < schema.getAttributeCount(); i++)
{
AttributeDescriptor descriptor = schema.getDescriptor(i);
columnMap.put(i, descriptor.getLocalName());
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

public List<Map<String, Object>> GetMapList()
{
CheckSource();

try {
List<Map<String, Object>> ret = new ArrayList<>();
try(SimpleFeatureIterator features = source.getFeatures().features()) {
while(features.hasNext())
{
SimpleFeature feature = features.next();
Map<String, Object> map = new HashMap<>();
for (int i = 0; i < feature.getAttributeCount(); i++) {
Object attribute = feature.getAttribute(i);
if(attribute instanceof Geometry)
attribute = ((Geometry) attribute).toText();
map.put(columnMap.get(i), attribute);
}
ret.add(map);
}
}
return ret;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public <T> List<T> GetList(Class<T> clazz)
{
List<Map<String, Object>> maps = GetMapList();
return maps.stream().map((x) -> BeanUtil.mapToBean(x, clazz, false, CopyOptions.create())).collect(Collectors.toList());
}
}

+ 5
- 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/DecimalUtils.java Ver ficheiro

@@ -487,4 +487,9 @@ public class DecimalUtils {
return number.toString();
}
}

public static BigDecimal nullToZero(BigDecimal o)
{
return null == o ? BigDecimal.ZERO : o;
}
}

+ 108
- 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/DB.java Ver ficheiro

@@ -0,0 +1,108 @@
package com.ruoyi.common.utils.sql;

import com.ruoyi.common.utils.spring.SpringUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.util.function.Supplier;

public final class DB
{
private static class TransactionHandle
{
private final PlatformTransactionManager manager;
private final TransactionStatus transactionStatus;

private TransactionHandle(PlatformTransactionManager manager, TransactionStatus transactionStatus)
{
this.manager = manager;
this.transactionStatus = transactionStatus;
}

private static TransactionHandle Cast(Object handle)
{
return (TransactionHandle) handle;
}
}

public static Object BeginTransaction()
{
PlatformTransactionManager manager = SpringUtils.getBean(PlatformTransactionManager.class);
TransactionDefinition definition = SpringUtils.getBean(TransactionDefinition.class);
TransactionStatus transaction = manager.getTransaction(definition);
return new TransactionHandle(manager, transaction);
}

public static void CommitTransaction(Object handle)
{
TransactionHandle transaction = (TransactionHandle) handle;
transaction.manager.commit(transaction.transactionStatus);
}

public static void RollbackTransaction(Object handle)
{
TransactionHandle transaction = TransactionHandle.Cast(handle);
transaction.manager.rollback(transaction.transactionStatus);
}

public static void EndTransaction(Object handle)
{
if(null == handle)
return;

TransactionHandle transaction = TransactionHandle.Cast(handle);
try
{
transaction.manager.commit(transaction.transactionStatus);
}
catch(Exception e)
{
e.printStackTrace();
transaction.manager.rollback(transaction.transactionStatus);
throw new RuntimeException(e);
}
}

public static void Transaction(Runnable runnable)
{
PlatformTransactionManager manager = SpringUtils.getBean(PlatformTransactionManager.class);
TransactionDefinition definition = SpringUtils.getBean(TransactionDefinition.class);
TransactionStatus transaction = manager.getTransaction(definition);
try
{
runnable.run();
manager.commit(transaction);
}
catch(Exception e)
{
e.printStackTrace();
manager.rollback(transaction);
throw new RuntimeException(e);
}
}

public static <T> T Transaction(Supplier<T> runnable, T...ifExceptRet)
{
PlatformTransactionManager manager = SpringUtils.getBean(PlatformTransactionManager.class);
TransactionDefinition definition = SpringUtils.getBean(TransactionDefinition.class);
TransactionStatus transaction = manager.getTransaction(definition);
try
{
T res = runnable.get();
manager.commit(transaction);
return res;
}
catch(Exception e)
{
e.printStackTrace();
manager.rollback(transaction);
if(null != ifExceptRet && ifExceptRet.length > 0)
return ifExceptRet[0];
else
throw new RuntimeException(e);
}
}

private DB() {}
}

Carregando…
Cancelar
Guardar