|
@@ -1,26 +1,24 @@
|
|
|
package com.zjugis.yzt.service.impl;
|
|
|
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.zjugis.yzt.beans.entity.StNzydk;
|
|
|
-import com.zjugis.yzt.dao.StGddkMapper;
|
|
|
import com.zjugis.yzt.dao.StNzydkMapper;
|
|
|
import com.zjugis.yzt.service.StNzydkService;
|
|
|
import com.zjugis.yzt.utils.ExcelUtils;
|
|
|
+import com.zjugis.yzt.utils.ZipFileProcessor;
|
|
|
import com.zjugis.yzt.utils.geocomm.ParseResult;
|
|
|
import com.zjugis.yzt.utils.geocomm.TxtReader;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.FileInputStream;
|
|
|
-import java.io.FileOutputStream;
|
|
|
import java.io.IOException;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.util.*;
|
|
|
-import java.util.zip.ZipEntry;
|
|
|
-import java.util.zip.ZipInputStream;
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @program: yh_yzt
|
|
@@ -33,68 +31,38 @@ import java.util.zip.ZipInputStream;
|
|
|
public class StNzydkServiceImpl extends ServiceImpl<StNzydkMapper, StNzydk> implements StNzydkService {
|
|
|
|
|
|
@Override
|
|
|
- public boolean uploadNzydkData(MultipartFile zipFile) {
|
|
|
+ public List<String> uploadNzydkData(MultipartFile zipFile) {
|
|
|
+ List<String> errorList = new ArrayList<>();
|
|
|
if (zipFile.isEmpty()) {
|
|
|
- log.error("上传文件为空");
|
|
|
- return false;
|
|
|
+ String msg = "上传文件为空";
|
|
|
+ log.error(msg);
|
|
|
+ errorList.add(msg);
|
|
|
+ return errorList;
|
|
|
}
|
|
|
|
|
|
File tempDir = null;
|
|
|
try {
|
|
|
- // 创建临时目录
|
|
|
- tempDir = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());
|
|
|
- System.out.println("tempDir:" + tempDir.getAbsolutePath());
|
|
|
- if (!tempDir.exists()) {
|
|
|
- tempDir.mkdirs();
|
|
|
- }
|
|
|
-
|
|
|
- // 解压ZIP文件
|
|
|
- Map<String, File> txtFiles = new HashMap<>();
|
|
|
- File xlsxFile = null;
|
|
|
-
|
|
|
- try (ZipInputStream zis = new ZipInputStream(zipFile.getInputStream())) {
|
|
|
- ZipEntry entry;
|
|
|
- while ((entry = zis.getNextEntry()) != null) {
|
|
|
- File newFile = new File(tempDir, entry.getName());
|
|
|
- if (entry.isDirectory()) {
|
|
|
- newFile.mkdirs();
|
|
|
- } else {
|
|
|
- // 确保父目录存在
|
|
|
- new File(newFile.getParent()).mkdirs();
|
|
|
- try (FileOutputStream fos = new FileOutputStream(newFile)) {
|
|
|
- byte[] buffer = new byte[1024];
|
|
|
- int len;
|
|
|
- while ((len = zis.read(buffer)) > 0) {
|
|
|
- fos.write(buffer, 0, len);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (newFile.getName().toLowerCase().endsWith(".xlsx")) {
|
|
|
- xlsxFile = newFile;
|
|
|
- } else if (newFile.getName().toLowerCase().endsWith(".txt")) {
|
|
|
- String fileNameWithoutExt = newFile.getName().substring(0, newFile.getName().lastIndexOf('.'));
|
|
|
- txtFiles.put(fileNameWithoutExt, newFile);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (xlsxFile == null) {
|
|
|
- log.error("ZIP包中未找到XLSX文件");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
+ ZipFileProcessor.ZipProcessResult zipProcessResult = ZipFileProcessor.processZipFile(zipFile);
|
|
|
+ Map<String, File> txtFiles = zipProcessResult.getTxtFiles();
|
|
|
+ File xlsxFile = zipProcessResult.getXlsxFile();
|
|
|
+ tempDir = zipProcessResult.getTempDir();
|
|
|
// --- Start: 使用 ExcelUtils.importExcel 解析 XLSX 文件 ---
|
|
|
Map<String, Map<String, Object>> batchInfoMap = new HashMap<>();
|
|
|
- List<Map<String, Object>> projectInfoList = new ArrayList<>();
|
|
|
-
|
|
|
|
|
|
int batchSheetIndex = 0;
|
|
|
int projectSheetIndex = 1;
|
|
|
|
|
|
- List<Map<String, Object>> batchDataList = ExcelUtils.importExcel(
|
|
|
- new FileInputStream(xlsxFile), xlsxFile.getName(), 0, 1, batchSheetIndex
|
|
|
- );
|
|
|
+ List<Map<String, Object>> batchDataList;
|
|
|
+ try {
|
|
|
+ batchDataList = ExcelUtils.importExcel(
|
|
|
+ new FileInputStream(xlsxFile), xlsxFile.getName(), 0, 1, batchSheetIndex
|
|
|
+ );
|
|
|
+ } catch (Exception e) {
|
|
|
+ String msg = "解析批次信息sheet失败: " + e.getMessage();
|
|
|
+ log.error(msg, e);
|
|
|
+ errorList.add(msg);
|
|
|
+ return errorList;
|
|
|
+ }
|
|
|
if (!batchDataList.isEmpty()) {
|
|
|
Map<String, Object> batchData = batchDataList.get(0);
|
|
|
String pcbh = batchData.containsKey("批次索引") ? String.valueOf(batchData.get("批次索引")) : null;
|
|
@@ -102,15 +70,26 @@ public class StNzydkServiceImpl extends ServiceImpl<StNzydkMapper, StNzydk> impl
|
|
|
batchInfoMap.put(pcbh, batchData);
|
|
|
}
|
|
|
} else {
|
|
|
- log.warn("未能从 '农转用批次信息' sheet 读取到数据。");
|
|
|
+ String msg = "未能从 '农转用批次信息' sheet 读取到数据。";
|
|
|
+ log.warn(msg);
|
|
|
+ errorList.add(msg);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- projectInfoList = ExcelUtils.importExcel(
|
|
|
- new FileInputStream(xlsxFile), xlsxFile.getName(), 0, 1, projectSheetIndex
|
|
|
- );
|
|
|
+ List<Map<String, Object>> projectInfoList;
|
|
|
+ try {
|
|
|
+ projectInfoList = ExcelUtils.importExcel(
|
|
|
+ new FileInputStream(xlsxFile), xlsxFile.getName(), 0, 1, projectSheetIndex
|
|
|
+ );
|
|
|
+ } catch (Exception e) {
|
|
|
+ String msg = "解析项目信息sheet失败: " + e.getMessage();
|
|
|
+ log.error(msg, e);
|
|
|
+ errorList.add(msg);
|
|
|
+ return errorList;
|
|
|
+ }
|
|
|
if (projectInfoList.isEmpty()) {
|
|
|
- log.warn("未能从 '农转用项目信息' sheet 读取到数据。");
|
|
|
+ String msg = "未能从 '农转用项目信息' sheet 读取到数据。";
|
|
|
+ log.warn(msg);
|
|
|
+ errorList.add(msg);
|
|
|
}
|
|
|
|
|
|
// --- End: 使用 ExcelUtils.importExcel 解析 XLSX 文件 ---
|
|
@@ -130,7 +109,9 @@ public class StNzydkServiceImpl extends ServiceImpl<StNzydkMapper, StNzydk> impl
|
|
|
stNzydk.setPzMj(parseBigDecimal(batchInfo.containsKey("批次总面积(公顷)") ? String.valueOf(batchInfo.get("批次总面积(公顷)")) : null));
|
|
|
stNzydk.setNmjf(batchInfo.containsKey("是否农民建房") ? String.valueOf(batchInfo.get("是否农民建房")) : null);
|
|
|
} else {
|
|
|
- log.warn("未找到批次索引为 {} 的批次信息,项目 {} 将跳过批次信息填充。", pcbh, projectInfo.containsKey("项目编号") ? String.valueOf(projectInfo.get("项目编号")) : "未知项目");
|
|
|
+ String msg = String.format("未找到批次索引为 %s 的批次信息,项目 %s 将跳过批次信息填充。", pcbh, projectInfo.containsKey("项目编号") ? String.valueOf(projectInfo.get("项目编号")) : "未知项目");
|
|
|
+ log.warn(msg);
|
|
|
+ errorList.add(msg);
|
|
|
}
|
|
|
|
|
|
// 项目信息
|
|
@@ -142,45 +123,61 @@ public class StNzydkServiceImpl extends ServiceImpl<StNzydkMapper, StNzydk> impl
|
|
|
stNzydk.setDkMj(parseBigDecimal(projectInfo.containsKey("项目面积(公顷)") ? String.valueOf(projectInfo.get("项目面积(公顷)")) : null));
|
|
|
stNzydk.setDkQs(projectInfo.containsKey("用地主体") ? String.valueOf(projectInfo.get("用地主体")) : null);
|
|
|
stNzydk.setBz(projectInfo.containsKey("备注") ? String.valueOf(projectInfo.get("备注")) : null);
|
|
|
+ // 保存到数据库前,先通过 dkBh 删除已存在的记录
|
|
|
+ if (stNzydk.getDkBh() != null) {
|
|
|
+ // 构造查询条件
|
|
|
+ QueryWrapper<StNzydk> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("dk_bh", stNzydk.getDkBh());
|
|
|
+ // 删除已存在的记录
|
|
|
+ try {
|
|
|
+ this.remove(queryWrapper);
|
|
|
+ } catch (Exception e) {
|
|
|
+ String msg = String.format("删除项目编号为 %s 的旧数据失败: %s", stNzydk.getDkBh(), e.getMessage());
|
|
|
+ log.error(msg, e);
|
|
|
+ errorList.add(msg);
|
|
|
+ }
|
|
|
+ }
|
|
|
// 保存到数据库
|
|
|
- if (!this.save(stNzydk)) {
|
|
|
- log.error("保存农转用数据失败:{}", stNzydk.getDkBh());
|
|
|
- return false;
|
|
|
+ try {
|
|
|
+ if (!this.save(stNzydk)) {
|
|
|
+ String msg = String.format("保存农转用数据失败:%s", stNzydk.getDkBh());
|
|
|
+ log.error(msg);
|
|
|
+ errorList.add(msg);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ String msg = String.format("保存农转用数据异常:%s,错误:%s", stNzydk.getDkBh(), e.getMessage());
|
|
|
+ log.error(msg, e);
|
|
|
+ errorList.add(msg);
|
|
|
+ continue;
|
|
|
}
|
|
|
// 获取保存后的objectid
|
|
|
Integer objectId = stNzydk.getObjectid();
|
|
|
if (objectId == null) {
|
|
|
- log.error("获取保存后的objectid失败:{}", stNzydk.getDkBh());
|
|
|
- return false;
|
|
|
+ String msg = String.format("获取保存后的objectid失败:%s", stNzydk.getDkBh());
|
|
|
+ log.error(msg);
|
|
|
+ errorList.add(msg);
|
|
|
+ continue;
|
|
|
}
|
|
|
// 解析图形信息
|
|
|
String projectCode = stNzydk.getDkBh();
|
|
|
File txtFile = txtFiles.get(projectCode);
|
|
|
- if (txtFile != null) {
|
|
|
- try (FileInputStream txtInputStream = new FileInputStream(txtFile)) {
|
|
|
- TxtReader txtReader = new TxtReader(txtInputStream);
|
|
|
- ParseResult parseResult = txtReader.read();
|
|
|
- if (parseResult != null && parseResult.getGeometry() != null) {
|
|
|
- String wkt = parseResult.getGeometry().toText();
|
|
|
- ((StNzydkMapper) this.baseMapper).updateShapeById(objectId, wkt, 4528);
|
|
|
- } else {
|
|
|
- log.warn("项目 {} 的TXT文件解析失败或未获取到Geometry数据。", projectCode);
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("解析项目 {} 的TXT文件失败: {}", projectCode, e.getMessage());
|
|
|
- }
|
|
|
- } else {
|
|
|
- log.warn("未找到项目 {} 对应的TXT界址点文件。", projectCode);
|
|
|
+ try {
|
|
|
+ updateShapeWithErrorList(objectId, projectCode, txtFile, errorList);
|
|
|
+ } catch (Exception e) {
|
|
|
+ String msg = String.format("项目 %s 的TXT文件解析异常: %s", projectCode, e.getMessage());
|
|
|
+ log.error(msg, e);
|
|
|
+ errorList.add(msg);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
+ return errorList;
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
- log.error("文件上传或处理失败", e);
|
|
|
- return false;
|
|
|
+ String msg = "文件上传或处理失败: " + e.getMessage();
|
|
|
+ log.error(msg, e);
|
|
|
+ errorList.add(msg);
|
|
|
+ return errorList;
|
|
|
} finally {
|
|
|
// 清理临时文件
|
|
|
if (tempDir != null && tempDir.exists()) {
|
|
@@ -189,6 +186,31 @@ public class StNzydkServiceImpl extends ServiceImpl<StNzydkMapper, StNzydk> impl
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void updateShapeWithErrorList(Integer objectId, String projectCode, File txtFile, List<String> errorList) {
|
|
|
+ if (txtFile != null) {
|
|
|
+ try (FileInputStream txtInputStream = new FileInputStream(txtFile)) {
|
|
|
+ TxtReader txtReader = new TxtReader(txtInputStream);
|
|
|
+ ParseResult parseResult = txtReader.read();
|
|
|
+ if (parseResult != null && parseResult.getGeometry() != null) {
|
|
|
+ String wkt = parseResult.getGeometry().toText();
|
|
|
+ ((StNzydkMapper) this.baseMapper).updateShapeById(objectId, wkt, 4528);
|
|
|
+ } else {
|
|
|
+ String msg = String.format("项目 %s 的TXT文件解析失败或未获取到Geometry数据。", projectCode);
|
|
|
+ log.warn(msg);
|
|
|
+ errorList.add(msg);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ String msg = String.format("解析项目 %s 的TXT文件失败: %s", projectCode, e.getMessage());
|
|
|
+ log.error(msg, e);
|
|
|
+ errorList.add(msg);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ String msg = String.format("未找到项目 %s 对应的TXT界址点文件。", projectCode);
|
|
|
+ log.warn(msg);
|
|
|
+ errorList.add(msg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private BigDecimal parseBigDecimal(String value) {
|
|
|
if (value == null || value.isEmpty()) {
|
|
|
return null;
|