From 7d8aeedcf26caecb4adb5482d4655740ba1f1af0 Mon Sep 17 00:00:00 2001
From: ZZX9599 <536509593@qq.com>
Date: Tue, 25 Nov 2025 14:27:10 +0800
Subject: [PATCH] =?UTF-8?q?=E5=85=A8=E9=83=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
geo.html | 26 ++--
.../java/com/yj/earth/auth/AuthGenerator.java | 4 +-
.../java/com/yj/earth/auth/AuthValidator.java | 8 +-
.../business/controller/AuthController.java | 4 +-
.../business/controller/DeviceController.java | 53 +++++++-
.../controller/FileInfoController.java | 10 +-
.../controller/IconLibraryController.java | 16 +--
.../controller/MilitaryLibraryController.java | 16 +--
.../controller/ModelLibraryController.java | 70 ++++++----
.../business/controller/PoiController.java | 6 +-
.../controller/PoiInfoController.java | 8 +-
.../business/controller/SystemController.java | 16 +--
.../business/controller/TsPlanController.java | 113 +++++++++++++----
.../service/impl/FileInfoServiceImpl.java | 2 +-
.../service/impl/SourceServiceImpl.java | 10 +-
.../common/convert/MilitaryConverter.java | 4 +-
.../earth/common/convert/ModelConverter.java | 4 +-
.../common/service/SourceDataGenerator.java | 6 +-
.../com/yj/earth/common/util/NetUtils.java | 120 ++++++++++++++++++
.../com/yj/earth/common/util/PoiExporter.java | 16 +--
.../com/yj/earth/common/util/SQLiteUtil.java | 64 +++++-----
.../com/yj/earth/common/util/SdkUtil.java | 2 +-
.../yj/earth/datasource/DatabaseManager.java | 2 +-
23 files changed, 414 insertions(+), 166 deletions(-)
create mode 100644 src/main/java/com/yj/earth/common/util/NetUtils.java
diff --git a/geo.html b/geo.html
index 4b9e63b..33703cc 100644
--- a/geo.html
+++ b/geo.html
@@ -106,7 +106,7 @@
路径参数
-
+
@@ -514,7 +514,7 @@
document.getElementById('resultContainer').classList.add('hidden');
}
- // 清空所有:起点重置为空(而非默认坐标)
+ // 清空所有: 起点重置为空(而非默认坐标)
function clearAll() {
clearRoute();
@@ -578,7 +578,7 @@
});
if (response.data.code !== 200 || !response.data.data || !response.data.data[0]) {
- throw new Error(`上传失败:${response.data.message || '未知错误'}`);
+ throw new Error(`上传失败: ${response.data.message || '未知错误'}`);
}
const fileId = response.data.data[0].id;
@@ -587,7 +587,7 @@
} catch (error) {
const errorMsg = error.response?.data?.message || error.message || '上传异常';
updateLoadProgress(false);
- alert(`⚠️ 上传失败:${errorMsg}`);
+ alert(`⚠️ 上传失败: ${errorMsg}`);
throw error;
}
}
@@ -600,7 +600,7 @@
const response = await axios.post(`${API_BASE_URL}/graphhopper/loadMap`, formData);
if (response.data.code !== 200) {
- throw new Error(`加载失败:${response.data.message || '接口返回异常'}`);
+ throw new Error(`加载失败: ${response.data.message || '接口返回异常'}`);
}
updateLoadProgress(false);
@@ -612,7 +612,7 @@
} catch (error) {
const errorMsg = error.response?.data?.message || error.message || '加载异常';
updateLoadProgress(false);
- alert(`⚠️ 地图加载失败:${errorMsg}`);
+ alert(`⚠️ 地图加载失败: ${errorMsg}`);
throw error;
}
}
@@ -662,13 +662,13 @@
);
if (response.data.code !== 200 || !response.data.data) {
- throw new Error(`计算失败:${response.data.message || '接口返回异常'}`);
+ throw new Error(`计算失败: ${response.data.message || '接口返回异常'}`);
}
handleRouteResponse(response.data.data);
} catch (error) {
const errorMsg = error.response?.data?.message || error.message || '计算异常';
- alert(`⚠️ 路径计算失败:${errorMsg}`);
+ alert(`⚠️ 路径计算失败: ${errorMsg}`);
} finally {
calcBtn.disabled = false;
calcBtn.innerHTML = '
计算路径';
@@ -691,12 +691,12 @@
routeLine = L.polyline(latLngs, lineStyles[document.getElementById('profile').value])
.addTo(map)
- .bindPopup(`
距离:${routeData.distanceKm.toFixed(2)} 公里
时间:${routeData.timeMinutes} 分钟
`);
+ .bindPopup(`
距离: ${routeData.distanceKm.toFixed(2)} 公里
时间: ${routeData.timeMinutes} 分钟
`);
map.fitBounds(routeLine.getBounds(), {padding: [50, 50], maxZoom: 14});
}
- // 事件绑定:移除起点按钮弹窗
+ // 事件绑定: 移除起点按钮弹窗
function bindEvents() {
// 文件选择相关
document.getElementById('selectFileBtn').addEventListener('click', () => {
@@ -713,7 +713,7 @@
const file = e.target.files[0];
if (file.name.toLowerCase().endsWith('.pbf')) {
const fileSizeMB = (file.size / (1024 * 1024)).toFixed(2);
- fileInfoEl.textContent = `已选择:${file.name}(${fileSizeMB} MB)`;
+ fileInfoEl.textContent = `已选择: ${file.name}(${fileSizeMB} MB)`;
fileInfoEl.className = 'mt-1 text-sm text-gray-600';
} else {
fileInfoEl.textContent = '❌ 请选择PBF格式的地图文件';
@@ -736,11 +736,11 @@
fileInput.value = '';
document.getElementById('fileInfo').classList.add('hidden');
} catch (error) {
- console.error('地图加载失败:', error);
+ console.error('地图加载失败: ', error);
}
});
- // 起点按钮:移除弹窗、仅保留地图选点逻辑
+ // 起点按钮: 移除弹窗、仅保留地图选点逻辑
document.getElementById('setStartBtn').addEventListener('click', () => {
map.once('click', (e) => setStartPoint(e.latlng.lat, e.latlng.lng));
});
diff --git a/src/main/java/com/yj/earth/auth/AuthGenerator.java b/src/main/java/com/yj/earth/auth/AuthGenerator.java
index 738befd..8182c5f 100644
--- a/src/main/java/com/yj/earth/auth/AuthGenerator.java
+++ b/src/main/java/com/yj/earth/auth/AuthGenerator.java
@@ -85,9 +85,9 @@ public class AuthGenerator {
// 将授权字符串写入文件
Files.write(licPath, authContent.getBytes(StandardCharsets.UTF_8));
- System.out.println("授权文件生成成功:" + licPath.toAbsolutePath());
+ System.out.println("授权文件生成成功: " + licPath.toAbsolutePath());
} catch (Exception e) {
- System.err.println("生成授权文件失败:" + e.getMessage());
+ System.err.println("生成授权文件失败: " + e.getMessage());
e.printStackTrace();
}
}
diff --git a/src/main/java/com/yj/earth/auth/AuthValidator.java b/src/main/java/com/yj/earth/auth/AuthValidator.java
index 2ea5af8..a5bf3d2 100644
--- a/src/main/java/com/yj/earth/auth/AuthValidator.java
+++ b/src/main/java/com/yj/earth/auth/AuthValidator.java
@@ -100,15 +100,15 @@ public class AuthValidator {
String serverUniqueId = ServerUniqueIdUtil.getServerUniqueId();
// 生成授权
String authString = AuthGenerator.generateAuth("标准版", 1000, 30, "35A0DF1D05AEAE77E1E2715CC36A7368");
- System.out.println("授权字符串:" + authString);
+ System.out.println("授权字符串: " + authString);
// 验证授权
boolean isValid = AuthValidator.validateAuth(authString, serverUniqueId);
- System.out.println("授权是否有效:" + isValid);
+ System.out.println("授权是否有效: " + isValid);
int remainingDays = AuthValidator.getRemainingDays(authString);
- System.out.println("剩余天数:" + remainingDays);
+ System.out.println("剩余天数: " + remainingDays);
AuthInfo authInfo = AuthValidator.getAuthInfo(authString);
- System.out.println("授权信息:" + authInfo);
+ System.out.println("授权信息: " + authInfo);
}
}
diff --git a/src/main/java/com/yj/earth/business/controller/AuthController.java b/src/main/java/com/yj/earth/business/controller/AuthController.java
index 29c0b39..e7da2af 100644
--- a/src/main/java/com/yj/earth/business/controller/AuthController.java
+++ b/src/main/java/com/yj/earth/business/controller/AuthController.java
@@ -61,7 +61,7 @@ public class AuthController {
Files.write(path, authContent.getBytes(StandardCharsets.UTF_8));
return ApiResponse.success(null);
} catch (Exception e) {
- return ApiResponse.failure("导入授权文件失败:" + e.getMessage());
+ return ApiResponse.failure("导入授权文件失败: " + e.getMessage());
}
}
@@ -80,7 +80,7 @@ public class AuthController {
AuthInfo authInfo = AuthValidator.getAuthInfo(authContent);
return ApiResponse.success(authInfo);
} catch (Exception e) {
- return ApiResponse.failure("获取授权信息失败:" + e.getMessage());
+ return ApiResponse.failure("获取授权信息失败: " + e.getMessage());
}
}
}
diff --git a/src/main/java/com/yj/earth/business/controller/DeviceController.java b/src/main/java/com/yj/earth/business/controller/DeviceController.java
index 323dc8f..1bf86a7 100644
--- a/src/main/java/com/yj/earth/business/controller/DeviceController.java
+++ b/src/main/java/com/yj/earth/business/controller/DeviceController.java
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yj.earth.business.domain.Device;
import com.yj.earth.business.service.DeviceService;
import com.yj.earth.common.util.ApiResponse;
+import com.yj.earth.common.util.NetUtils;
import com.yj.earth.vo.AddDeviceDto;
import com.yj.earth.dto.device.ImportDeviceDto;
import com.yj.earth.dto.device.UpdateDeviceDto;
@@ -27,6 +28,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
+import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
@Tag(name = "设备信息管理")
@@ -73,14 +75,57 @@ public class DeviceController {
}
@GetMapping("/list")
- @Operation(summary = "查询设备信息")
- public ApiResponse listDevice(@Parameter(description = "分页数量") Integer pageNum, @Parameter(description = "分页大小") Integer pageSize,@Parameter(description = "设备名称") String cameraName) {
+ @Operation(summary = "查询设备信息(含在线状态)")
+ public ApiResponse listDevice(
+ @Parameter(description = "分页数量") Integer pageNum,
+ @Parameter(description = "分页大小") Integer pageSize,
+ @Parameter(description = "设备名称") String cameraName
+ ) {
LambdaQueryWrapper
queryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(cameraName)) {
queryWrapper.like(Device::getCameraName, cameraName);
}
+
+ // 执行标准的分页查询
Page devicePage = deviceService.page(new Page<>(pageNum, pageSize), queryWrapper);
- return ApiResponse.success(devicePage);
+ List deviceList = devicePage.getRecords();
+
+ if (CollectionUtils.isEmpty(deviceList)) {
+ // 如果没有数据,直接返回空分页
+ return ApiResponse.success(devicePage);
+ }
+
+ try {
+ // 提取所有设备的 IP 地址、用于批量检测
+ List ipAddresses = deviceList.stream()
+ .map(Device::getIp)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+
+ // 异步并发检测所有 IP 的在线状态
+ Map reachabilityMap = NetUtils.checkReachabilityAsync(ipAddresses);
+
+ // 更新设备状态:遍历设备列表,根据 IP 设置 status 字段
+ deviceList.forEach(device -> {
+ String ip = device.getIp();
+ if (ip != null) {
+ Boolean isOnline = reachabilityMap.get(ip);
+ // 根据 Ping 结果设置 status: 1 为在线,0 为离线
+ device.setStatus(isOnline != null && isOnline ? 1 : 0);
+ } else {
+ // 如果 IP 地址为空,直接设置为离线
+ device.setStatus(0);
+ }
+ });
+
+ // 直接返回更新后的分页对象
+ return ApiResponse.success(devicePage);
+
+ } catch (ExecutionException | InterruptedException e) {
+ // 恢复线程中断状态
+ Thread.currentThread().interrupt();
+ return ApiResponse.success(devicePage);
+ }
}
@GetMapping("/delete")
@@ -270,7 +315,7 @@ public class DeviceController {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("设备信息导入模板", "UTF-8").replaceAll("\\+", "%20");
- response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
+ response.setHeader("Content-disposition", "attachment;filename*=" + fileName + ".xlsx");
// 写入模板表头(通过空数据列表触发表头生成)
EasyExcel.write(response.getOutputStream(), ImportDeviceDto.class)
.sheet("设备信息")
diff --git a/src/main/java/com/yj/earth/business/controller/FileInfoController.java b/src/main/java/com/yj/earth/business/controller/FileInfoController.java
index 4cd8315..5a8f9ad 100644
--- a/src/main/java/com/yj/earth/business/controller/FileInfoController.java
+++ b/src/main/java/com/yj/earth/business/controller/FileInfoController.java
@@ -193,7 +193,7 @@ public class FileInfoController {
// 标准化路径
targetFilePath = Paths.get(fileAbsolutePath).toRealPath();
- // 校验文件合法性:是否存在、是否为普通文件
+ // 校验文件合法性: 是否存在、是否为普通文件
BasicFileAttributes fileAttr = Files.readAttributes(targetFilePath, BasicFileAttributes.class);
if (!fileAttr.isRegularFile()) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
@@ -214,7 +214,7 @@ public class FileInfoController {
}
response.setContentLengthLong(fileAttr.size());
- // 关键修改:将attachment改为inline实现预览
+ // 关键修改: 将attachment改为inline实现预览
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
"inline; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
@@ -231,13 +231,13 @@ public class FileInfoController {
} catch (NoSuchFileException e) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
- fileInfoService.writeResponseMessage(response, "文件不存在:" + fileAbsolutePath);
+ fileInfoService.writeResponseMessage(response, "文件不存在: " + fileAbsolutePath);
} catch (SecurityException e) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
- fileInfoService.writeResponseMessage(response, "访问拒绝:无权限读取该文件");
+ fileInfoService.writeResponseMessage(response, "访问拒绝: 无权限读取该文件");
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- fileInfoService.writeResponseMessage(response, "预览失败:" + e.getMessage());
+ fileInfoService.writeResponseMessage(response, "预览失败: " + e.getMessage());
}
}
}
diff --git a/src/main/java/com/yj/earth/business/controller/IconLibraryController.java b/src/main/java/com/yj/earth/business/controller/IconLibraryController.java
index 2fc1d27..1d487c1 100644
--- a/src/main/java/com/yj/earth/business/controller/IconLibraryController.java
+++ b/src/main/java/com/yj/earth/business/controller/IconLibraryController.java
@@ -71,22 +71,22 @@ public class IconLibraryController {
if (!parentDir.exists()) {
boolean mkdirsSuccess = parentDir.mkdirs();
if (!mkdirsSuccess) {
- return ApiResponse.failure("创建父目录失败:" + folderPath);
+ return ApiResponse.failure("创建父目录失败: " + folderPath);
}
}
// 校验图标库文件是否已存在
if (iconFile.exists()) {
if (iconFile.isDirectory()) {
- return ApiResponse.failure("同名目录已存在、无法创建文件:" + iconPath);
+ return ApiResponse.failure("同名目录已存在、无法创建文件: " + iconPath);
}
- return ApiResponse.failure("图标库文件已存在:" + iconPath);
+ return ApiResponse.failure("图标库文件已存在: " + iconPath);
}
// 创建SQLite文件
boolean createFileSuccess = iconFile.createNewFile();
if (!createFileSuccess) {
- return ApiResponse.failure("创建图标库文件失败:" + iconPath);
+ return ApiResponse.failure("创建图标库文件失败: " + iconPath);
}
// 初始化图标库表结构
@@ -95,7 +95,7 @@ public class IconLibraryController {
addIconLibrary(iconPath);
return ApiResponse.success(null);
} catch (Exception e) {
- return ApiResponse.failure("创建图标库失败:" + e.getMessage());
+ return ApiResponse.failure("创建图标库失败: " + e.getMessage());
}
}
@@ -107,13 +107,13 @@ public class IconLibraryController {
// 校验路径是否存在
File iconFile = new File(iconPath);
if (!iconFile.exists() || !iconFile.isFile()) {
- return ApiResponse.failure("图标库文件不存在:" + iconPath);
+ return ApiResponse.failure("图标库文件不存在: " + iconPath);
}
// 添加到配置表并启用
addIconLibrary(iconPath);
return ApiResponse.success(null);
} catch (Exception e) {
- return ApiResponse.failure("导入图标库失败:" + e.getMessage());
+ return ApiResponse.failure("导入图标库失败: " + e.getMessage());
}
}
@@ -136,7 +136,7 @@ public class IconLibraryController {
iconPath, checkParentSql, parentParams, IconType.class
);
if (parentType == null) {
- return ApiResponse.failure("父级图标类型不存在:" + parentId);
+ return ApiResponse.failure("父级图标类型不存在: " + parentId);
}
}
diff --git a/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java b/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java
index 719e8b9..77cec6e 100644
--- a/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java
+++ b/src/main/java/com/yj/earth/business/controller/MilitaryLibraryController.java
@@ -81,22 +81,22 @@ public class MilitaryLibraryController {
if (!parentDir.exists()) {
boolean mkdirsSuccess = parentDir.mkdirs();
if (!mkdirsSuccess) {
- return ApiResponse.failure("创建父目录失败:" + folderPath);
+ return ApiResponse.failure("创建父目录失败: " + folderPath);
}
}
// 校验军标库文件是否已存在
if (militaryFile.exists()) {
if (militaryFile.isDirectory()) {
- return ApiResponse.failure("同名目录已存在、无法创建文件:" + militaryPath);
+ return ApiResponse.failure("同名目录已存在、无法创建文件: " + militaryPath);
}
- return ApiResponse.failure("军标库文件已存在:" + militaryPath);
+ return ApiResponse.failure("军标库文件已存在: " + militaryPath);
}
// 创建SQLite文件
boolean createFileSuccess = militaryFile.createNewFile();
if (!createFileSuccess) {
- return ApiResponse.failure("创建军标库文件失败:" + militaryPath);
+ return ApiResponse.failure("创建军标库文件失败: " + militaryPath);
}
// 初始化军标库表结构
@@ -105,7 +105,7 @@ public class MilitaryLibraryController {
addMilitaryLibrary(militaryPath);
return ApiResponse.success(null);
} catch (Exception e) {
- return ApiResponse.failure("创建军标库失败:" + e.getMessage());
+ return ApiResponse.failure("创建军标库失败: " + e.getMessage());
}
}
@@ -117,13 +117,13 @@ public class MilitaryLibraryController {
// 校验路径是否存在
File militaryFile = new File(militaryPath);
if (!militaryFile.exists() || !militaryFile.isFile()) {
- return ApiResponse.failure("军标库文件不存在:" + militaryPath);
+ return ApiResponse.failure("军标库文件不存在: " + militaryPath);
}
// 添加到配置表并启用
addMilitaryLibrary(militaryPath);
return ApiResponse.success(null);
} catch (Exception e) {
- return ApiResponse.failure("导入军标库失败:" + e.getMessage());
+ return ApiResponse.failure("导入军标库失败: " + e.getMessage());
}
}
@@ -146,7 +146,7 @@ public class MilitaryLibraryController {
militaryPath, checkParentSql, parentParams, MilitaryType.class
);
if (parentType == null) {
- return ApiResponse.failure("父级军标类型不存在:" + parentId);
+ return ApiResponse.failure("父级军标类型不存在: " + parentId);
}
}
diff --git a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java
index dcc1666..0f9066f 100644
--- a/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java
+++ b/src/main/java/com/yj/earth/business/controller/ModelLibraryController.java
@@ -81,27 +81,27 @@ public class ModelLibraryController {
if (!parentDir.exists()) {
boolean mkdirsSuccess = parentDir.mkdirs();
if (!mkdirsSuccess) {
- return ApiResponse.failure("创建父目录失败:" + folderPath);
+ return ApiResponse.failure("创建父目录失败: " + folderPath);
}
}
// 检查模型库文件是否已存在
if (modelFile.exists()) {
if (modelFile.isDirectory()) {
- return ApiResponse.failure("同名目录已存在、无法创建文件:" + modelPath);
+ return ApiResponse.failure("同名目录已存在、无法创建文件: " + modelPath);
}
- return ApiResponse.failure("模型库文件已存在:" + modelPath);
+ return ApiResponse.failure("模型库文件已存在: " + modelPath);
}
// 创建模型库文件(
boolean createSuccess = modelFile.createNewFile();
if (!createSuccess) {
- return ApiResponse.failure("创建模型库文件失败:" + modelPath);
+ return ApiResponse.failure("创建模型库文件失败: " + modelPath);
}
// 添加模型库信息
addModelLibrary(modelPath);
SQLiteUtil.initializationModel(modelPath);
return ApiResponse.success(null);
} catch (Exception e) {
- return ApiResponse.failure("创建模型库失败:" + e.getMessage());
+ return ApiResponse.failure("创建模型库失败: " + e.getMessage());
}
}
@@ -174,7 +174,7 @@ public class ModelLibraryController {
@Operation(summary = "模型类型列表")
@GetMapping("/modelTypeList")
- public ApiResponse modelTypeTree(@Parameter(description = "模型名称") @RequestParam("modelName") String modelName) throws SQLException, IllegalAccessException, InstantiationException {
+ public ApiResponse modelTypeTree(@Parameter(description = "模型名称") @RequestParam(value = "modelName",required = false) String modelName) throws SQLException, IllegalAccessException, InstantiationException {
return ApiResponse.success(modelTypeList(modelName));
}
@@ -190,7 +190,7 @@ public class ModelLibraryController {
return ApiResponse.failure("请先创建或导入模型库");
}
- // 简化校验:仅判断列表是否为空
+ // 简化校验: 仅判断列表是否为空
if (filePaths == null || filePaths.isEmpty()) {
return ApiResponse.failure("文件路径列表不能为空");
}
@@ -286,9 +286,12 @@ public class ModelLibraryController {
}
- @Operation(summary = "根据模型类型查看模型列表")
+ @Operation(summary = "根据模型类型和名称模糊查询模型列表")
@PostMapping("/modelList")
- public ApiResponse modelList(@Parameter(description = "模型类型ID") @RequestParam("modelTypeId") String modelTypeId) throws SQLException, IllegalAccessException, InstantiationException {
+ public ApiResponse modelList(
+ @Parameter(description = "模型类型ID") @RequestParam("modelTypeId") String modelTypeId,
+ @Parameter(description = "模型名称模糊查询") @RequestParam(value = "name", required = false) String name
+ ) throws SQLException, IllegalAccessException, InstantiationException {
// 获取最新的模型库
String modelPath = getModelLibrary();
if (modelPath == null) {
@@ -298,15 +301,15 @@ public class ModelLibraryController {
// 获取分类ID及其所有子分类ID的列表
List typeIdList = getModelTypeIdsWithChildren(modelTypeId);
if (typeIdList.isEmpty()) {
- return ApiResponse.success(null);
+ return ApiResponse.success(Collections.emptyList());
}
String idsWithQuotes = typeIdList.stream()
.map(id -> "'" + id + "'")
.collect(Collectors.joining(","));
- // 多表联查、查询所有指定分类及其子分类下的模型
- String sql = """
+ // 构建SQL语句
+ StringBuilder sql = new StringBuilder("""
SELECT
model.id,
model.model_type_id as modelTypeId,
@@ -318,12 +321,18 @@ public class ModelLibraryController {
model_type.name as modelTypeName
FROM model
JOIN model_type ON model.model_type_id = model_type.id
- WHERE model.model_type_id IN (?)
- """.replace("?", idsWithQuotes);
+ WHERE model.model_type_id IN (%s)
+ """.formatted(idsWithQuotes));
+
+ // 如果传入了名称、则增加模糊查询条件
+ if (name != null && !name.trim().isEmpty()) {
+ // 直接拼接SQL、注意SQL注入风险
+ sql.append(" AND model.model_name LIKE '%" + name.trim() + "%'");
+ }
+
+ // 执行查询
+ List modelVos = SQLiteUtil.queryForList(modelPath, sql.toString(), null, ModelVo.class);
- // 使用所有分类ID作为查询参数
- List