This commit is contained in:
2025-11-20 15:10:08 +08:00
parent 5a77756c33
commit ca13d078a3
12 changed files with 216 additions and 203 deletions

View File

@ -150,10 +150,10 @@ public class GraphHopperController {
public ApiResponse calculateRoute(@RequestBody RouteRequest request) {
// 区分未加载地图和加载中两种状态
if (isLoading.get()) {
return ApiResponse.failure("地图正在加载中请稍后再试");
return ApiResponse.failure("地图正在加载中请稍后再试");
}
if (!isLoaded.get() || currentHopper == null) {
return ApiResponse.failure("地图未加载请先加载地图");
return ApiResponse.failure("地图未加载请先加载地图");
}
try {
// 构建路径点列表

View File

@ -33,6 +33,7 @@ import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
@ -200,29 +201,16 @@ public class IconLibraryController {
@Operation(summary = "添加图标文件")
@PostMapping("/addIconFile")
public ApiResponse addIconFile(@RequestParam("files") MultipartFile[] files, @RequestParam("iconTypeId") @Parameter(description = "图标类型ID") String typeId) throws IOException, SQLException, IllegalAccessException, InstantiationException {
// 获取当前启用的图标库
public ApiResponse addIconFile(@RequestParam("filePaths") List<String> filePaths, @RequestParam("iconTypeId") String typeId) throws Exception {
// 获取当前启用的图标库路径
String iconPath = getIconLibrary();
if (iconPath == null) {
return ApiResponse.failure("请先创建或导入图标库");
}
// 校验类型是否存在
if (!isIconTypeExist(iconPath, typeId)) {
return ApiResponse.failure("图标类型不存在:" + typeId);
}
// 循环处理每个文件
for (MultipartFile file : files) {
if (file.isEmpty()) {
continue; // 跳过空文件
}
// 循环处理每个绝对路径对应的文件
for (String filePath : filePaths) {
File file = new File(filePath);
// 解析文件名与后缀
String originalFileName = file.getOriginalFilename();
if (originalFileName == null) {
continue;
}
String originalFileName = file.getName();
String fileSuffix = FileUtil.extName(originalFileName);
String fileNameWithoutSuffix = FileUtil.mainName(originalFileName);
@ -235,10 +223,10 @@ public class IconLibraryController {
params.add(typeId);
params.add(fileNameWithoutSuffix);
params.add(fileSuffix);
params.add(file.getBytes());
params.add(Files.readAllBytes(file.toPath()));
params.add(LocalDateTime.now().toString());
System.out.println(insertSql);
// 执行数据库插入
SQLiteUtil.executeUpdate(iconPath, insertSql, params);
}
@ -391,7 +379,7 @@ public class IconLibraryController {
private String getIconLibrary() {
LambdaQueryWrapper<IconLibrary> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(IconLibrary::getIsEnable, 1); // 1=启用、0=未启用
queryWrapper.eq(IconLibrary::getIsEnable, 1);
IconLibrary library = iconLibraryService.getOne(queryWrapper);
return library == null ? null : library.getPath();
}

View File

@ -1,21 +1,32 @@
package com.yj.earth.business.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yj.earth.business.domain.Matter;
import com.yj.earth.business.domain.Source;
import com.yj.earth.business.service.MatterService;
import com.yj.earth.business.service.SourceService;
import com.yj.earth.common.util.ApiResponse;
import com.yj.earth.common.util.JsonUtil;
import com.yj.earth.dto.matter.AddMatterDto;
import com.yj.earth.dto.matter.UpdateMatterDto;
import com.yj.earth.params.Point;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Tag(name = "物资数据管理")
@ -24,6 +35,8 @@ import java.util.List;
public class MatterController {
@Resource
private MatterService matterService;
@Resource
private SourceService sourceService;
@PostMapping("/add")
@Operation(summary = "添加物资")
@ -71,10 +84,122 @@ public class MatterController {
public ApiResponse list(@Parameter(description = "分页数量") @RequestParam(value = "pageNum") Integer pageNum,
@Parameter(description = "分页大小") @RequestParam(value = "pageSize") Integer pageSize,
@Parameter(description = "物资名称") @RequestParam(value = "name", required = false) String name) {
LambdaQueryWrapper<Matter> queryWrapper = new LambdaQueryWrapper<>();
Map<String, Integer> goodsTotalMap = getGoodCountMap();
// 分页查询物资表的数据
LambdaQueryWrapper<Matter> matterWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(name)) {
queryWrapper.like(Matter::getName, name);
matterWrapper.like(Matter::getName, name);
}
return ApiResponse.success(matterService.page(new Page<>(pageNum, pageSize), queryWrapper));
Page<Matter> matterPage = matterService.page(new Page<>(pageNum, pageSize), matterWrapper);
// 用统计出的数量替换分页结果中的数量
if (!CollectionUtils.isEmpty(matterPage.getRecords())) {
matterPage.getRecords().forEach(matter -> {
String matterName = matter.getName();
Integer count = goodsTotalMap.get(matterName);
if (count != null) {
matter.setNum(count);
}
});
}
return ApiResponse.success(matterPage);
}
@Operation(summary = "物资统计")
@PostMapping("/statistics")
public ApiResponse statistics(@Parameter(description = "点ID列表") @RequestBody List<String> pointIdList) {
// 构建Source表的查询条件
LambdaQueryWrapper<Source> sourceWrapper = new LambdaQueryWrapper<>();
// 根据ID列表查询
sourceWrapper.in(Source::getId, pointIdList);
// 执行查询、获取所有符合条件的Source列表
List<Source> sourceList = sourceService.list(sourceWrapper);
// 初始化物资统计Map用于存储 "物资名称 -> 总数量" 的映射关系
Map<String, Integer> goodsTotalMap = new HashMap<>();
if (!CollectionUtils.isEmpty(sourceList)) {
for (Source source : sourceList) {
try {
Point point = JsonUtil.jsonToObject(source.getParams(), Point.class);
if (point == null) continue;
Optional.ofNullable(point.getAttribute())
.map(Point.Attribute::getGoods)
.map(Point.Attribute.Goods::getContent)
.ifPresent(contentList -> {
// 遍历物资列表中的每个物资项
for (Point.Attribute.Goods.GoodsContent goodsContent : contentList) {
if (goodsContent == null) continue;
// 处理物资名称
String goodsName = Optional.ofNullable(goodsContent.getName())
.orElse("未知物资");
// 处理物资数量
int count = Optional.ofNullable(goodsContent.getCnt())
.map(Integer::valueOf)
.orElse(0);
// 累加物资总数量
goodsTotalMap.merge(goodsName, count, Integer::sum);
}
});
} catch (Exception e) {
}
}
}
// 返回最终的物资统计Map
return ApiResponse.success(goodsTotalMap);
}
private Map<String, Integer> getGoodCountMap() {
// 构建Source表的查询条件
LambdaQueryWrapper<Source> sourceWrapper = new LambdaQueryWrapper<>();
sourceWrapper.eq(Source::getSourceType, "point");
// 执行查询、获取所有符合条件的Source列表
List<Source> sourceList = sourceService.list(sourceWrapper);
// 初始化物资统计Map用于存储 "物资名称 -> 总数量" 的映射关系
Map<String, Integer> goodsTotalMap = new HashMap<>();
if (!CollectionUtils.isEmpty(sourceList)) {
for (Source source : sourceList) {
try {
Point point = JsonUtil.jsonToObject(source.getParams(), Point.class);
if (point == null) continue;
Optional.ofNullable(point.getAttribute())
.map(Point.Attribute::getGoods)
.map(Point.Attribute.Goods::getContent)
.ifPresent(contentList -> {
// 遍历物资列表中的每个物资项
for (Point.Attribute.Goods.GoodsContent goodsContent : contentList) {
if (goodsContent == null) continue;
// 处理物资名称
String goodsName = Optional.ofNullable(goodsContent.getName())
.orElse("未知物资");
// 处理物资数量
int count = Optional.ofNullable(goodsContent.getCnt())
.map(Integer::valueOf)
.orElse(0);
// 累加物资总数量
goodsTotalMap.merge(goodsName, count, Integer::sum);
}
});
} catch (Exception e) {
}
}
}
// 返回最终的物资统计Map
return goodsTotalMap;
}
}

View File

@ -33,6 +33,7 @@ import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
@ -200,29 +201,16 @@ public class MilitaryLibraryController {
@Operation(summary = "添加军标文件")
@PostMapping("/addMilitaryFile")
public ApiResponse addMilitaryFile(@RequestParam("files") MultipartFile[] files, @RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId) throws IOException, SQLException, IllegalAccessException, InstantiationException {
// 获取当前启用的军标库
public ApiResponse addMilitaryFile(@RequestParam("filePaths") List<String> filePaths,
@RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId) throws IOException, SQLException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 校验类型是否存在
if (!isMilitaryTypeExist(militaryPath, typeId)) {
return ApiResponse.failure("军标类型不存在:" + typeId);
}
// 循环处理每个文件
for (MultipartFile file : files) {
if (file.isEmpty()) {
continue; // 跳过空文件
}
// 循环处理每个绝对路径对应的文件
for (String filePath : filePaths) {
File file = new File(filePath);
// 解析文件名与后缀
String originalFileName = file.getOriginalFilename();
if (originalFileName == null) {
continue;
}
String originalFileName = file.getName();
String fileSuffix = FileUtil.extName(originalFileName);
String fileNameWithoutSuffix = FileUtil.mainName(originalFileName);
@ -235,7 +223,7 @@ public class MilitaryLibraryController {
params.add(typeId);
params.add(fileNameWithoutSuffix);
params.add(fileSuffix);
params.add(file.getBytes());
params.add(Files.readAllBytes(file.toPath()));
params.add(LocalDateTime.now().toString());
SQLiteUtil.executeUpdate(militaryPath, insertSql, params);
@ -243,7 +231,6 @@ public class MilitaryLibraryController {
return ApiResponse.success(null);
}
@Operation(summary = "获取军标文件数据")
@GetMapping("/data/military/{militaryId}/{fileSuffix}")
public ResponseEntity<byte[]> getMilitaryData(@PathVariable("militaryId") @Parameter(description = "军标ID") String militaryId, @PathVariable("fileSuffix") @Parameter(description = "军标文件后缀") String fileSuffix) {

View File

@ -16,6 +16,7 @@ import com.yj.earth.dto.modelLibrary.AddModelTypeDto;
import com.yj.earth.dto.modelLibrary.CreateModelLibraryDto;
import com.yj.earth.dto.modelLibrary.DragModelTypeDto;
import com.yj.earth.dto.modelLibrary.UpdateModelTypeNameDto;
import com.yj.earth.vo.IconDataVo;
import com.yj.earth.vo.ModelDataVo;
import com.yj.earth.vo.ModelTypeVo;
import com.yj.earth.vo.ModelVo;
@ -36,6 +37,7 @@ import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.*;
@ -165,25 +167,24 @@ public class ModelLibraryController {
@Operation(summary = "添加模型文件")
@PostMapping("/addModelFile")
public ApiResponse addModelFile(@RequestParam("files") MultipartFile[] files, @Parameter(description = "模型类型ID") @RequestParam("modelTypeId") String modelTypeId) throws IOException, SQLException {
public ApiResponse addModelFile(
@Parameter(description = "绝对文件路径列表") @RequestParam("filePaths") List<String> filePaths,
@Parameter(description = "模型类型ID") @RequestParam("modelTypeId") String modelTypeId) throws IOException, SQLException {
// 获取最新的模型库路径
String modelPath = getModelLibrary();
if (modelPath == null) {
return ApiResponse.failure("请先创建或导入模型库");
}
// 循环处理每个上传的文件
for (MultipartFile file : files) {
// 跳过空文件
if (file.isEmpty()) {
continue;
}
// 获取文件信息
String fileName = file.getOriginalFilename();
if (fileName == null) {
continue;
}
String fileSuffix = FileUtil.extName(fileName);
String fileNameWithoutSuffix = FileUtil.mainName(fileName);
// 简化校验:仅判断列表是否为空
if (filePaths == null || filePaths.isEmpty()) {
return ApiResponse.failure("文件路径列表不能为空");
}
// 循环处理每个文件路径
for (String filePath : filePaths) {
File file = new File(filePath);
// 构建插入SQL
String sql = "INSERT INTO model " +
@ -194,9 +195,9 @@ public class ModelLibraryController {
String modelId = UUID.fastUUID().toString(true);
params.add(modelId);
params.add(modelTypeId);
params.add(fileNameWithoutSuffix);
params.add(fileSuffix);
params.add(file.getBytes());
params.add(file.getName().split("\\.")[0]);
params.add(file.getName().substring(file.getName().lastIndexOf(".") + 1));
params.add(Files.readAllBytes(file.toPath()));
params.add(LocalDateTime.now());
// 执行插入操作

View File

@ -34,7 +34,7 @@ public class PoiController {
Class.forName("org.sqlite.JDBC");
String dbPath = System.getProperty("user.dir") + File.separator + "poi" + File.separator + "poi.db";
connection = DriverManager.getConnection("jdbc:sqlite:" + dbPath);
logger.info("POI数据库连接初始化成功路径:{}", dbPath);
logger.info("POI数据库连接初始化成功路径:{}", dbPath);
}
}

View File

@ -50,6 +50,7 @@ public class TsSourceController {
public ApiResponse update(@RequestBody UpdateTsSourceDto updateTsSourceDto) {
TsSource tsSource = new TsSource();
BeanUtils.copyProperties(updateTsSourceDto, tsSource);
tsSourceService.updateById(tsSource);
return ApiResponse.success(null);
}

View File

@ -49,14 +49,16 @@ public class JsonUtil {
}
}
/**
* 将 JSON 字符串转换为指定类型的对象
*/
public static <T> T jsonToObject(String json, Class<T> clazz) {
if (json == null || json.trim().isEmpty()) {
return null;
}
return objectMapper.convertValue(json, clazz);
try {
return objectMapper.readValue(json, clazz);
} catch (Exception e) {
return null;
}
}
/**

View File

@ -90,7 +90,7 @@ public class SQLiteUtil {
stmt.execute("PRAGMA busy_timeout=2000;"); // 忙等待超时2秒避免瞬时并发锁等待
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("初始化SQLite数据源失败路径" + dbFilePath + "+ 原因是:" + e.getMessage());
throw new RuntimeException("请检查路径是否存在");
}
return dataSource;

View File

@ -141,11 +141,11 @@ public class DatabaseManager {
public static String getSqliteDbFilePath() {
if (!isPathInitialized || FOLDER_NAME == null) {
throw new IllegalStateException("数据库路径尚未初始化请先调用 initializePath 方法或等待 @PostConstruct 完成");
throw new IllegalStateException("数据库路径尚未初始化请先调用 initializePath 方法或等待 @PostConstruct 完成");
}
if (sqliteDbFilePath == null) {
// 如果没有预先创建则动态构建路径
// 如果没有预先创建则动态构建路径
Path appDir = Paths.get(FOLDER_NAME);
Path dbFile = appDir.resolve(DB_FILE_NAME);
sqliteDbFilePath = dbFile.toAbsolutePath().toString();
@ -208,7 +208,7 @@ public class DatabaseManager {
// 直接使用配置的绝对路径
if (FOLDER_NAME == null || FOLDER_NAME.trim().isEmpty()) {
throw new IOException("server.path 配置为空无法创建SQLite数据库文件");
throw new IOException("server.path 配置为空无法创建SQLite数据库文件");
}
Path appDir = Paths.get(FOLDER_NAME);
@ -484,10 +484,10 @@ public class DatabaseManager {
DatabaseManager.initializePath(serverPath);
log.info("已提前初始化数据库路径: {}", serverPath);
} else {
log.warn("未找到 server.path 配置将等待 @PostConstruct 初始化");
log.warn("未找到 server.path 配置将等待 @PostConstruct 初始化");
}
} catch (Exception e) {
log.warn("提前初始化数据库路径失败将等待 @PostConstruct 初始化: {}", e.getMessage());
log.warn("提前初始化数据库路径失败将等待 @PostConstruct 初始化: {}", e.getMessage());
}
}
}

View File

@ -1,104 +0,0 @@
package com.yj.earth.word;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STShd;
import java.io.FileOutputStream;
import java.io.IOException;
public class GenerateDocx {
public static void main(String[] args) {
// 创建文档对象
XWPFDocument document = new XWPFDocument();
try {
// 添加标题段落
XWPFParagraph titlePara = document.createParagraph();
titlePara.setAlignment(ParagraphAlignment.CENTER);
XWPFRun titleRun = titlePara.createRun();
titleRun.setText("POI 生成 Docx 示例");
// 字体大小
titleRun.setFontSize(20);
// 加粗
titleRun.setBold(true);
// 字体
titleRun.setFontFamily("宋体");
// 添加正文段落
XWPFParagraph contentPara1 = document.createParagraph();
contentPara1.setAlignment(ParagraphAlignment.LEFT);
XWPFRun run1 = contentPara1.createRun();
run1.setText("这是使用 Apache POI 生成的 docx 文档。");
run1.setFontSize(12);
run1.setFontFamily("微软雅黑");
// 换行
XWPFParagraph contentPara2 = document.createParagraph();
XWPFRun run2 = contentPara2.createRun();
run2.setText("支持设置文本样式,如:");
run2.setFontSize(12);
// 文本样式示例(同一行不同样式)
XWPFRun run3 = contentPara2.createRun();
run3.setText(" 加粗 ");
run3.setBold(true);
XWPFRun run4 = contentPara2.createRun();
run4.setText(" 斜体 ");
run4.setItalic(true);
XWPFRun run5 = contentPara2.createRun();
run5.setText(" 下划线 ");
run5.setUnderline(UnderlinePatterns.SINGLE); // 单下划线
XWPFRun run6 = contentPara2.createRun();
run6.setText(" 红色 ");
run6.setColor("FF0000"); // 红色
// 添加表格
int rows = 3; // 3行
int cols = 3; // 3列
XWPFTable table = document.createTable(rows, cols);
table.setWidth("100%"); // 表格宽度
// 设置表头
XWPFTableRow headerRow = table.getRow(0);
headerRow.getCell(0).setText("ID");
headerRow.getCell(1).setText("名称");
headerRow.getCell(2).setText("描述");
// 表头背景色(浅灰色)
for (XWPFTableCell cell : headerRow.getTableCells()) {
CTShd cTShd = cell.getCTTc().addNewTcPr().addNewShd();
cTShd.setVal(STShd.CLEAR);
cTShd.setFill("D9D9D9"); // 浅灰色
}
// 设置表格内容
XWPFTableRow row1 = table.getRow(1);
row1.getCell(0).setText("1");
row1.getCell(1).setText("POI");
row1.getCell(2).setText("处理 Office 文档的 Java 库");
XWPFTableRow row2 = table.getRow(2);
row2.getCell(0).setText("2");
row2.getCell(1).setText("Docx");
row2.getCell(2).setText("Word 2007+ 格式");
// 保存文档到本地
FileOutputStream out = new FileOutputStream("poi-demo.docx");
document.write(out);
out.close();
System.out.println("docx 生成成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
document.close(); // 关闭文档,释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
}
}