全部
This commit is contained in:
@ -77,7 +77,7 @@ public class AuthGenerator {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try {
|
try {
|
||||||
// 生成加密的授权字符串
|
// 生成加密的授权字符串
|
||||||
String authContent = generateAuth("标准版", 1000, 365, "3A446222D1FE537F6C9EEF5C2AB3F957");
|
String authContent = generateAuth("标准版", 1000, 365, "8B1FB12E9F8E80109724989E0B25773B");
|
||||||
|
|
||||||
// 定义授权文件路径(当前目录下的 yjearth.YJ)
|
// 定义授权文件路径(当前目录下的 yjearth.YJ)
|
||||||
Path licPath = Paths.get("yjearth.YJ");
|
Path licPath = Paths.get("yjearth.YJ");
|
||||||
|
|||||||
@ -19,37 +19,46 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Tag(name = "CSV文件解析")
|
@Tag(name = "CSV文件解析")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/csv")
|
@RequestMapping("/csv")
|
||||||
public class CsvController {
|
public class CsvController {
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/parseCsv")
|
@GetMapping("/parseCsv")
|
||||||
@Operation(summary = "解析CSV文件")
|
@Operation(summary = "解析CSV文件")
|
||||||
public ApiResponse parseCsv(@Parameter(description = "文件路径") @RequestParam String filePath) {
|
public ApiResponse parseCsv(@Parameter(description = "文件路径") @RequestParam String filePath) {
|
||||||
Map<String, Object> response = new HashMap<>();
|
|
||||||
List<CsvField> fieldList = new ArrayList<>();
|
List<CsvField> fieldList = new ArrayList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
|
// 验证文件是否存在
|
||||||
|
if (!file.exists()) {
|
||||||
|
return ApiResponse.failure("文件不存在");
|
||||||
|
}
|
||||||
|
|
||||||
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), "GBK");
|
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), "GBK");
|
||||||
CSVParser parser = new CSVParser(reader, CSVFormat.DEFAULT)) {
|
CSVParser parser = new CSVParser(reader, CSVFormat.DEFAULT)) {
|
||||||
// 遍历所有行(CSVRecord即一行数据)
|
// 遍历所有行、跳过第一行(下标为0)
|
||||||
for (CSVRecord record : parser) {
|
for (CSVRecord record : parser) {
|
||||||
|
// 跳过表头行(第一行)
|
||||||
|
if (record.getRecordNumber() == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// 确保每行至少有3列(A、B、C列)
|
// 确保每行至少有3列(A、B、C列)
|
||||||
if (record.size() >= 3) {
|
if (record.size() >= 3) {
|
||||||
String label = record.get(1).trim();
|
String label = record.get(1).trim();
|
||||||
String key = record.get(2).trim();
|
String key = record.get(2).trim();
|
||||||
fieldList.add(new CsvField(key, label));
|
if (!key.isEmpty() && !label.isEmpty()) {
|
||||||
|
fieldList.add(new CsvField(key, label));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ApiResponse.success(fieldList);
|
return ApiResponse.success(fieldList);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return ApiResponse.failure(e.getMessage());
|
return ApiResponse.failure("解析失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,7 +91,7 @@ public class DeviceController {
|
|||||||
List<Device> deviceList = devicePage.getRecords();
|
List<Device> deviceList = devicePage.getRecords();
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(deviceList)) {
|
if (CollectionUtils.isEmpty(deviceList)) {
|
||||||
// 如果没有数据,直接返回空分页
|
// 如果没有数据、直接返回空分页
|
||||||
return ApiResponse.success(devicePage);
|
return ApiResponse.success(devicePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,15 +105,15 @@ public class DeviceController {
|
|||||||
// 异步并发检测所有 IP 的在线状态
|
// 异步并发检测所有 IP 的在线状态
|
||||||
Map<String, Boolean> reachabilityMap = NetUtils.checkReachabilityAsync(ipAddresses);
|
Map<String, Boolean> reachabilityMap = NetUtils.checkReachabilityAsync(ipAddresses);
|
||||||
|
|
||||||
// 更新设备状态:遍历设备列表,根据 IP 设置 status 字段
|
// 更新设备状态:遍历设备列表、根据 IP 设置 status 字段
|
||||||
deviceList.forEach(device -> {
|
deviceList.forEach(device -> {
|
||||||
String ip = device.getIp();
|
String ip = device.getIp();
|
||||||
if (ip != null) {
|
if (ip != null) {
|
||||||
Boolean isOnline = reachabilityMap.get(ip);
|
Boolean isOnline = reachabilityMap.get(ip);
|
||||||
// 根据 Ping 结果设置 status: 1 为在线,0 为离线
|
// 根据 Ping 结果设置 status: 1 为在线、0 为离线
|
||||||
device.setStatus(isOnline != null && isOnline ? 1 : 0);
|
device.setStatus(isOnline != null && isOnline ? 1 : 0);
|
||||||
} else {
|
} else {
|
||||||
// 如果 IP 地址为空,直接设置为离线
|
// 如果 IP 地址为空、直接设置为离线
|
||||||
device.setStatus(0);
|
device.setStatus(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -36,10 +36,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Tag(name = "图标数据管理")
|
@Tag(name = "图标数据管理")
|
||||||
@ -194,8 +191,8 @@ public class IconLibraryController {
|
|||||||
|
|
||||||
@Operation(summary = "图标类型树形列表")
|
@Operation(summary = "图标类型树形列表")
|
||||||
@GetMapping("/iconTypeTree")
|
@GetMapping("/iconTypeTree")
|
||||||
public ApiResponse iconTypeTree() throws SQLException, IllegalAccessException, InstantiationException {
|
public ApiResponse iconTypeTree(@Parameter(description = "图标名称") @RequestParam(value = "iconName", required = false) String iconName) throws SQLException, IllegalAccessException, InstantiationException {
|
||||||
List<IconTypeVo> treeList = iconTypeList();
|
List<IconTypeVo> treeList = iconTypeList(iconName);
|
||||||
return ApiResponse.success(treeList);
|
return ApiResponse.success(treeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,48 +264,61 @@ public class IconLibraryController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "根据类型查询图标列表")
|
@Operation(summary = "根据类型和名称模糊查询图标列表")
|
||||||
@PostMapping("/iconList")
|
@PostMapping("/iconList")
|
||||||
public ApiResponse getIconList(@RequestParam("iconTypeId") @Parameter(description = "图标类型ID") String typeId) throws SQLException, IllegalAccessException, InstantiationException {
|
public ApiResponse getIconList(
|
||||||
|
@RequestParam("iconTypeId") @Parameter(description = "图标类型ID") String iconTypeId,
|
||||||
|
@Parameter(description = "图标名称模糊查询") @RequestParam(value = "name", required = false) String name)
|
||||||
|
throws SQLException, IllegalAccessException, InstantiationException {
|
||||||
String iconPath = getIconLibrary();
|
String iconPath = getIconLibrary();
|
||||||
if (iconPath == null) {
|
if (iconPath == null) {
|
||||||
return ApiResponse.failure("请先创建或导入图标库");
|
return ApiResponse.failure("请先创建或导入图标库");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前类型及所有子类型ID(递归)
|
// 获取当前类型及所有子类型ID(递归)
|
||||||
List<String> typeIdList = getIconTypeIdsWithChildren(typeId);
|
List<String> typeIdList = getIconTypeIdsWithChildren(iconTypeId);
|
||||||
if (typeIdList == null || typeIdList.isEmpty()) {
|
if (typeIdList == null || typeIdList.isEmpty()) {
|
||||||
return ApiResponse.success(new ArrayList<>());
|
return ApiResponse.success(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建IN条件(处理SQL注入风险)
|
// 构建IN条件
|
||||||
String idsWithQuotes = typeIdList.stream()
|
String idsWithQuotes = typeIdList.stream()
|
||||||
.map(id -> "'" + id + "'")
|
.map(id -> "'" + id + "'")
|
||||||
.collect(Collectors.joining(","));
|
.collect(Collectors.joining(","));
|
||||||
|
|
||||||
// 多表联查
|
// 构建SQL语句
|
||||||
String querySql = """
|
StringBuilder sql = new StringBuilder("""
|
||||||
SELECT
|
SELECT
|
||||||
i.id,
|
i.id,
|
||||||
i.icon_type_id as iconTypeId,
|
i.icon_type_id as iconTypeId,
|
||||||
i.icon_name as iconName,
|
i.icon_name as iconName,
|
||||||
i.icon_type as iconType,
|
i.icon_type as iconType,
|
||||||
i.created_at as createdAt,
|
i.created_at as createdAt,
|
||||||
i.updated_at as updatedAt,
|
i.updated_at as updatedAt,
|
||||||
t.name as iconTypeName
|
t.name as iconTypeName
|
||||||
FROM icon i
|
FROM icon i
|
||||||
JOIN icon_type t ON i.icon_type_id = t.id
|
JOIN icon_type t ON i.icon_type_id = t.id
|
||||||
WHERE i.icon_type_id IN (%s)
|
WHERE i.icon_type_id IN (%s)
|
||||||
ORDER BY i.created_at DESC
|
""".formatted(idsWithQuotes));
|
||||||
""".replace("%s", idsWithQuotes);
|
|
||||||
|
|
||||||
// 查询并转换为VO
|
// 如果传入了名称、则增加模糊查询条件
|
||||||
|
if (name != null && !name.trim().isEmpty()) {
|
||||||
|
// 直接拼接SQL、注意SQL注入风险
|
||||||
|
sql.append(" AND i.icon_name LIKE '%" + name.trim() + "%'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一添加排序条件
|
||||||
|
sql.append(" ORDER BY i.created_at DESC");
|
||||||
|
|
||||||
|
// 执行查询
|
||||||
List<IconVo> iconVoList = SQLiteUtil.queryForList(
|
List<IconVo> iconVoList = SQLiteUtil.queryForList(
|
||||||
iconPath, querySql, null, IconVo.class
|
iconPath, sql.toString(), null, IconVo.class
|
||||||
);
|
);
|
||||||
|
|
||||||
for (IconVo vo : iconVoList) {
|
for (IconVo vo : iconVoList) {
|
||||||
vo.setIconDataUrl("/iconLibrary/data/icon/" + vo.getId() + "/" + vo.getIconType());
|
vo.setIconDataUrl("/iconLibrary/data/icon/" + vo.getId() + "/" + vo.getIconType());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiResponse.success(iconVoList);
|
return ApiResponse.success(iconVoList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +383,7 @@ public class IconLibraryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 返回更新后的树形列表
|
// 返回更新后的树形列表
|
||||||
List<IconTypeVo> treeList = iconTypeList();
|
List<IconTypeVo> treeList = iconTypeList(null);
|
||||||
return ApiResponse.success(treeList);
|
return ApiResponse.success(treeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +391,10 @@ public class IconLibraryController {
|
|||||||
LambdaQueryWrapper<IconLibrary> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<IconLibrary> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.eq(IconLibrary::getIsEnable, 1);
|
queryWrapper.eq(IconLibrary::getIsEnable, 1);
|
||||||
IconLibrary library = iconLibraryService.getOne(queryWrapper);
|
IconLibrary library = iconLibraryService.getOne(queryWrapper);
|
||||||
return library == null ? null : library.getPath();
|
if(library == null){
|
||||||
|
throw new RuntimeException("请先创建或导入图标库");
|
||||||
|
}
|
||||||
|
return library.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addIconLibrary(String iconPath) {
|
private void addIconLibrary(String iconPath) {
|
||||||
@ -411,24 +424,44 @@ public class IconLibraryController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IconTypeVo> iconTypeList() throws SQLException, IllegalAccessException, InstantiationException {
|
/**
|
||||||
|
* 查询图标分类树形结构
|
||||||
|
*/
|
||||||
|
private List<IconTypeVo> iconTypeList(String iconName) throws SQLException, IllegalAccessException, InstantiationException {
|
||||||
String iconPath = getIconLibrary();
|
String iconPath = getIconLibrary();
|
||||||
if (iconPath == null) {
|
if (iconPath == null) {
|
||||||
return new ArrayList<>();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String querySql = """
|
// 构建基础SQL语句
|
||||||
SELECT
|
StringBuilder sqlBuilder = new StringBuilder("""
|
||||||
id, name, parent_id as parentId,
|
SELECT DISTINCT icon_type.id, icon_type.name, icon_type.parent_id,
|
||||||
tree_index as treeIndex, created_at as createdAt,
|
icon_type.tree_index, icon_type.created_at,
|
||||||
updated_at as updatedAt
|
icon_type.updated_at
|
||||||
FROM icon_type
|
FROM icon_type
|
||||||
ORDER BY tree_index ASC
|
""");
|
||||||
""";
|
|
||||||
List<IconType> typeList = SQLiteUtil.queryForList(iconPath, querySql, null, IconType.class);
|
|
||||||
|
|
||||||
// 构建树形结构
|
// 如果传入了图标名称、则拼接 JOIN 和 WHERE 条件
|
||||||
return buildIconTypeTree(typeList);
|
if (iconName != null && !iconName.trim().isEmpty()) {
|
||||||
|
String trimmedName = iconName.trim();
|
||||||
|
// 直接拼接SQL
|
||||||
|
sqlBuilder.append(" INNER JOIN icon ON icon_type.id = icon.icon_type_id");
|
||||||
|
sqlBuilder.append(" WHERE icon.icon_name LIKE '%" + trimmedName + "%'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为所有查询都加上统一的排序条件
|
||||||
|
sqlBuilder.append(" ORDER BY icon_type.tree_index ASC");
|
||||||
|
|
||||||
|
// 执行查询、获取符合条件的图标分类列表
|
||||||
|
List<IconType> iconTypes = SQLiteUtil.queryForList(
|
||||||
|
iconPath,
|
||||||
|
sqlBuilder.toString(),
|
||||||
|
null,
|
||||||
|
IconType.class
|
||||||
|
);
|
||||||
|
|
||||||
|
// 将扁平的分类列表转换为树形结构
|
||||||
|
return buildIconTypeTree(iconTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IconTypeVo> buildIconTypeTree(List<IconType> typeList) {
|
private List<IconTypeVo> buildIconTypeTree(List<IconType> typeList) {
|
||||||
|
|||||||
@ -204,8 +204,8 @@ public class MilitaryLibraryController {
|
|||||||
|
|
||||||
@Operation(summary = "军标类型树形列表")
|
@Operation(summary = "军标类型树形列表")
|
||||||
@GetMapping("/militaryTypeTree")
|
@GetMapping("/militaryTypeTree")
|
||||||
public ApiResponse militaryTypeTree() throws SQLException, IllegalAccessException, InstantiationException {
|
public ApiResponse militaryTypeTree(@Parameter(description = "军标名称") @RequestParam(value = "militaryName", required = false) String militaryName) throws SQLException, IllegalAccessException, InstantiationException {
|
||||||
List<MilitaryTypeVo> treeList = militaryTypeList();
|
List<MilitaryTypeVo> treeList = militaryTypeList(militaryName);
|
||||||
return ApiResponse.success(treeList);
|
return ApiResponse.success(treeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,6 +241,7 @@ public class MilitaryLibraryController {
|
|||||||
|
|
||||||
return ApiResponse.success(null);
|
return ApiResponse.success(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "获取军标文件数据")
|
@Operation(summary = "获取军标文件数据")
|
||||||
@GetMapping("/data/military/{militaryId}/{fileSuffix}")
|
@GetMapping("/data/military/{militaryId}/{fileSuffix}")
|
||||||
public ResponseEntity<byte[]> getMilitaryData(@PathVariable("militaryId") @Parameter(description = "军标ID") String militaryId, @PathVariable("fileSuffix") @Parameter(description = "军标文件后缀") String fileSuffix) {
|
public ResponseEntity<byte[]> getMilitaryData(@PathVariable("militaryId") @Parameter(description = "军标ID") String militaryId, @PathVariable("fileSuffix") @Parameter(description = "军标文件后缀") String fileSuffix) {
|
||||||
@ -275,48 +276,61 @@ public class MilitaryLibraryController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "根据类型查询军标列表")
|
@Operation(summary = "根据类型和名称模糊查询军标列表")
|
||||||
@PostMapping("/militaryList")
|
@PostMapping("/militaryList")
|
||||||
public ApiResponse getMilitaryList(@RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId) throws SQLException, IllegalAccessException, InstantiationException {
|
public ApiResponse getMilitaryList(
|
||||||
|
@RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String militaryTypeId,
|
||||||
|
@Parameter(description = "军标名称模糊查询") @RequestParam(value = "name", required = false) String name)
|
||||||
|
throws SQLException, IllegalAccessException, InstantiationException {
|
||||||
String militaryPath = getMilitaryLibrary();
|
String militaryPath = getMilitaryLibrary();
|
||||||
if (militaryPath == null) {
|
if (militaryPath == null) {
|
||||||
return ApiResponse.failure("请先创建或导入军标库");
|
return ApiResponse.failure("请先创建或导入军标库");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前类型及所有子类型ID(递归)
|
// 获取当前类型及所有子类型ID(递归)
|
||||||
List<String> typeIdList = getMilitaryTypeIdsWithChildren(typeId);
|
List<String> typeIdList = getMilitaryTypeIdsWithChildren(militaryTypeId);
|
||||||
if (typeIdList == null || typeIdList.isEmpty()) {
|
if (typeIdList == null || typeIdList.isEmpty()) {
|
||||||
return ApiResponse.success(new ArrayList<>());
|
return ApiResponse.success(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建IN条件(处理SQL注入风险)
|
// 构建IN条件
|
||||||
String idsWithQuotes = typeIdList.stream()
|
String idsWithQuotes = typeIdList.stream()
|
||||||
.map(id -> "'" + id + "'")
|
.map(id -> "'" + id + "'")
|
||||||
.collect(Collectors.joining(","));
|
.collect(Collectors.joining(","));
|
||||||
|
|
||||||
// 多表联查
|
// 构建SQL语句
|
||||||
String querySql = """
|
StringBuilder sql = new StringBuilder("""
|
||||||
SELECT
|
SELECT
|
||||||
m.id,
|
m.id,
|
||||||
m.military_type_id as militaryTypeId,
|
m.military_type_id as militaryTypeId,
|
||||||
m.military_name as militaryName,
|
m.military_name as militaryName,
|
||||||
m.military_type as militaryType,
|
m.military_type as militaryType,
|
||||||
m.created_at as createdAt,
|
m.created_at as createdAt,
|
||||||
m.updated_at as updatedAt,
|
m.updated_at as updatedAt,
|
||||||
t.name as militaryTypeName
|
t.name as militaryTypeName
|
||||||
FROM military m
|
FROM military m
|
||||||
JOIN military_type t ON m.military_type_id = t.id
|
JOIN military_type t ON m.military_type_id = t.id
|
||||||
WHERE m.military_type_id IN (%s)
|
WHERE m.military_type_id IN (%s)
|
||||||
ORDER BY m.created_at DESC
|
""".formatted(idsWithQuotes));
|
||||||
""".replace("%s", idsWithQuotes);
|
|
||||||
|
|
||||||
// 查询并转换为VO
|
// 如果传入了名称、则增加模糊查询条件
|
||||||
|
if (name != null && !name.trim().isEmpty()) {
|
||||||
|
// 直接拼接SQL、注意SQL注入风险
|
||||||
|
sql.append(" AND m.military_name LIKE '%" + name.trim() + "%'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一添加排序条件
|
||||||
|
sql.append(" ORDER BY m.created_at DESC");
|
||||||
|
|
||||||
|
// 执行查询
|
||||||
List<MilitaryVo> militaryVoList = SQLiteUtil.queryForList(
|
List<MilitaryVo> militaryVoList = SQLiteUtil.queryForList(
|
||||||
militaryPath, querySql, null, MilitaryVo.class
|
militaryPath, sql.toString(), null, MilitaryVo.class
|
||||||
);
|
);
|
||||||
|
|
||||||
for (MilitaryVo vo : militaryVoList) {
|
for (MilitaryVo vo : militaryVoList) {
|
||||||
vo.setMilitaryDataUrl("/militaryLibrary/data/military/" + vo.getId() + "/" + vo.getMilitaryType());
|
vo.setMilitaryDataUrl("/militaryLibrary/data/military/" + vo.getId() + "/" + vo.getMilitaryType());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiResponse.success(militaryVoList);
|
return ApiResponse.success(militaryVoList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +421,7 @@ public class MilitaryLibraryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 返回更新后的树形列表
|
// 返回更新后的树形列表
|
||||||
List<MilitaryTypeVo> treeList = militaryTypeList();
|
List<MilitaryTypeVo> treeList = militaryTypeList(null);
|
||||||
return ApiResponse.success(treeList);
|
return ApiResponse.success(treeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +429,10 @@ public class MilitaryLibraryController {
|
|||||||
LambdaQueryWrapper<MilitaryLibrary> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<MilitaryLibrary> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.eq(MilitaryLibrary::getIsEnable, 1); // 1=启用、0=未启用
|
queryWrapper.eq(MilitaryLibrary::getIsEnable, 1); // 1=启用、0=未启用
|
||||||
MilitaryLibrary library = militaryLibraryService.getOne(queryWrapper);
|
MilitaryLibrary library = militaryLibraryService.getOne(queryWrapper);
|
||||||
return library == null ? null : library.getPath();
|
if (library == null) {
|
||||||
|
throw new RuntimeException("请先创建或导入军标库");
|
||||||
|
}
|
||||||
|
return library.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMilitaryLibrary(String militaryPath) {
|
private void addMilitaryLibrary(String militaryPath) {
|
||||||
@ -445,24 +462,44 @@ public class MilitaryLibraryController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MilitaryTypeVo> militaryTypeList() throws SQLException, IllegalAccessException, InstantiationException {
|
/**
|
||||||
|
* 查询军标分类树形结构
|
||||||
|
*/
|
||||||
|
private List<MilitaryTypeVo> militaryTypeList(String militaryName) throws SQLException, IllegalAccessException, InstantiationException {
|
||||||
String militaryPath = getMilitaryLibrary();
|
String militaryPath = getMilitaryLibrary();
|
||||||
if (militaryPath == null) {
|
if (militaryPath == null) {
|
||||||
return new ArrayList<>();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String querySql = """
|
// 构建基础SQL语句
|
||||||
SELECT
|
StringBuilder sqlBuilder = new StringBuilder("""
|
||||||
id, name, parent_id as parentId,
|
SELECT DISTINCT military_type.id, military_type.name, military_type.parent_id,
|
||||||
tree_index as treeIndex, created_at as createdAt,
|
military_type.tree_index, military_type.created_at,
|
||||||
updated_at as updatedAt
|
military_type.updated_at
|
||||||
FROM military_type
|
FROM military_type
|
||||||
ORDER BY tree_index ASC
|
""");
|
||||||
""";
|
|
||||||
List<MilitaryType> typeList = SQLiteUtil.queryForList(militaryPath, querySql, null, MilitaryType.class);
|
|
||||||
|
|
||||||
// 构建树形结构
|
// 如果传入了军标名称、则拼接 JOIN 和 WHERE 条件
|
||||||
return buildMilitaryTypeTree(typeList);
|
if (militaryName != null && !militaryName.trim().isEmpty()) {
|
||||||
|
String trimmedName = militaryName.trim();
|
||||||
|
// 直接拼接SQL
|
||||||
|
sqlBuilder.append(" INNER JOIN military ON military_type.id = military.military_type_id");
|
||||||
|
sqlBuilder.append(" WHERE military.military_name LIKE '%" + trimmedName + "%'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为所有查询都加上统一的排序条件
|
||||||
|
sqlBuilder.append(" ORDER BY military_type.tree_index ASC");
|
||||||
|
|
||||||
|
// 执行查询、获取符合条件的军标分类列表
|
||||||
|
List<MilitaryType> militaryTypes = SQLiteUtil.queryForList(
|
||||||
|
militaryPath,
|
||||||
|
sqlBuilder.toString(),
|
||||||
|
null,
|
||||||
|
MilitaryType.class
|
||||||
|
);
|
||||||
|
|
||||||
|
// 将扁平的分类列表转换为树形结构
|
||||||
|
return buildMilitaryTypeTree(militaryTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MilitaryTypeVo> buildMilitaryTypeTree(List<MilitaryType> typeList) {
|
private List<MilitaryTypeVo> buildMilitaryTypeTree(List<MilitaryType> typeList) {
|
||||||
|
|||||||
@ -174,7 +174,7 @@ public class ModelLibraryController {
|
|||||||
|
|
||||||
@Operation(summary = "模型类型列表")
|
@Operation(summary = "模型类型列表")
|
||||||
@GetMapping("/modelTypeList")
|
@GetMapping("/modelTypeList")
|
||||||
public ApiResponse modelTypeTree(@Parameter(description = "模型名称") @RequestParam(value = "modelName",required = false) 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));
|
return ApiResponse.success(modelTypeList(modelName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,16 +463,16 @@ public class ModelLibraryController {
|
|||||||
|
|
||||||
// 构建基础SQL语句
|
// 构建基础SQL语句
|
||||||
StringBuilder sqlBuilder = new StringBuilder("""
|
StringBuilder sqlBuilder = new StringBuilder("""
|
||||||
SELECT DISTINCT model_type.id, model_type.name, model_type.parent_id,
|
SELECT DISTINCT model_type.id, model_type.name, model_type.parent_id,
|
||||||
model_type.tree_index, model_type.created_at,
|
model_type.tree_index, model_type.created_at,
|
||||||
model_type.updated_at
|
model_type.updated_at
|
||||||
FROM model_type
|
FROM model_type
|
||||||
""");
|
""");
|
||||||
|
|
||||||
// 如果传入了模型名称、则拼接 JOIN 和 WHERE 条件
|
// 如果传入了模型名称、则拼接 JOIN 和 WHERE 条件
|
||||||
if (modelName != null && !modelName.trim().isEmpty()) {
|
if (modelName != null && !modelName.trim().isEmpty()) {
|
||||||
String trimmedName = modelName.trim();
|
String trimmedName = modelName.trim();
|
||||||
// 直接拼接SQL、不做任何转义(存在SQL注入风险)
|
// 直接拼接SQL
|
||||||
sqlBuilder.append(" INNER JOIN model ON model_type.id = model.model_type_id");
|
sqlBuilder.append(" INNER JOIN model ON model_type.id = model.model_type_id");
|
||||||
sqlBuilder.append(" WHERE model.model_name LIKE '%" + trimmedName + "%'");
|
sqlBuilder.append(" WHERE model.model_name LIKE '%" + trimmedName + "%'");
|
||||||
}
|
}
|
||||||
@ -547,7 +547,7 @@ public class ModelLibraryController {
|
|||||||
queryWrapper.eq(ModelLibrary::getIsEnable, 1);
|
queryWrapper.eq(ModelLibrary::getIsEnable, 1);
|
||||||
ModelLibrary modelLibrary = modelLibraryService.getOne(queryWrapper);
|
ModelLibrary modelLibrary = modelLibraryService.getOne(queryWrapper);
|
||||||
if (modelLibrary == null) {
|
if (modelLibrary == null) {
|
||||||
return null;
|
throw new RuntimeException("请先创建或导入模型库");
|
||||||
}
|
}
|
||||||
return modelLibrary.getPath();
|
return modelLibrary.getPath();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,24 +88,19 @@ public class RoleController {
|
|||||||
if (status != null) {
|
if (status != null) {
|
||||||
queryWrapper.eq(Role::getStatus, status);
|
queryWrapper.eq(Role::getStatus, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 统计当前条件下每个角色名称的数量
|
|
||||||
List<Role> allMatchedRoles = roleService.list(queryWrapper);
|
|
||||||
Map<String, Long> roleNameCountMap = allMatchedRoles.stream()
|
|
||||||
.collect(Collectors.groupingBy(Role::getRoleName, Collectors.counting()));
|
|
||||||
|
|
||||||
// 分页查询
|
// 分页查询
|
||||||
Page<Role> rolePage = roleService.page(new Page<>(pageNum, pageSize), queryWrapper);
|
Page<Role> rolePage = roleService.page(new Page<>(pageNum, pageSize), queryWrapper);
|
||||||
|
|
||||||
// 转换为 Page<RoleVo>
|
// 转换为 Page<RoleVo>
|
||||||
Page<RoleVo> roleVoPage = (Page<RoleVo>) rolePage.convert(role -> {
|
Page<RoleVo> roleVoPage = (Page<RoleVo>) rolePage.convert(role -> {
|
||||||
|
LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
userQueryWrapper.eq(User::getRoleId, role.getId());
|
||||||
|
Long userCount = userService.count(userQueryWrapper);
|
||||||
RoleVo roleVo = new RoleVo();
|
RoleVo roleVo = new RoleVo();
|
||||||
BeanUtils.copyProperties(role, roleVo);
|
BeanUtils.copyProperties(role, roleVo);
|
||||||
// 设置数量
|
// 设置数量
|
||||||
roleVo.setCount(roleNameCountMap.getOrDefault(role.getRoleName(), 0L).intValue());
|
roleVo.setCount(Math.toIntExact(userCount));
|
||||||
return roleVo;
|
return roleVo;
|
||||||
});
|
});
|
||||||
|
|
||||||
return ApiResponse.success(roleVoPage);
|
return ApiResponse.success(roleVoPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -177,7 +177,7 @@ public class SystemController {
|
|||||||
source.setSourceType(resultSet.getString("source_type"));
|
source.setSourceType(resultSet.getString("source_type"));
|
||||||
source.setSourcePath(resultSet.getString("source_path"));
|
source.setSourcePath(resultSet.getString("source_path"));
|
||||||
|
|
||||||
// 关键修改: 读取原始parent_id、而非覆盖为新父节点ID
|
// 读取原始parent_id、而非覆盖为新父节点ID
|
||||||
source.setParentId(resultSet.getString("parent_id"));
|
source.setParentId(resultSet.getString("parent_id"));
|
||||||
|
|
||||||
Integer treeIndex = resultSet.getObject("tree_index") != null
|
Integer treeIndex = resultSet.getObject("tree_index") != null
|
||||||
|
|||||||
@ -50,6 +50,7 @@ public class TsEventController {
|
|||||||
public ApiResponse update(@RequestBody UpdateTsEventDto updateTsEventDto) {
|
public ApiResponse update(@RequestBody UpdateTsEventDto updateTsEventDto) {
|
||||||
TsEvent tsEvent = new TsEvent();
|
TsEvent tsEvent = new TsEvent();
|
||||||
BeanUtils.copyProperties(updateTsEventDto, tsEvent);
|
BeanUtils.copyProperties(updateTsEventDto, tsEvent);
|
||||||
|
tsEventService.updateById(tsEvent);
|
||||||
return ApiResponse.success(null);
|
return ApiResponse.success(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,9 +4,12 @@ import cn.dev33.satoken.stp.StpUtil;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.yj.earth.business.domain.Source;
|
||||||
import com.yj.earth.business.domain.TsPlan;
|
import com.yj.earth.business.domain.TsPlan;
|
||||||
|
import com.yj.earth.business.domain.TsSource;
|
||||||
import com.yj.earth.business.domain.User;
|
import com.yj.earth.business.domain.User;
|
||||||
import com.yj.earth.business.service.TsPlanService;
|
import com.yj.earth.business.service.TsPlanService;
|
||||||
|
import com.yj.earth.business.service.TsSourceService;
|
||||||
import com.yj.earth.business.service.UserService;
|
import com.yj.earth.business.service.UserService;
|
||||||
import com.yj.earth.common.util.ApiResponse;
|
import com.yj.earth.common.util.ApiResponse;
|
||||||
import com.yj.earth.dto.tsPlan.AddTsPlanDto;
|
import com.yj.earth.dto.tsPlan.AddTsPlanDto;
|
||||||
@ -21,6 +24,7 @@ import javax.annotation.Resource;
|
|||||||
import java.time.DateTimeException;
|
import java.time.DateTimeException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -36,6 +40,8 @@ public class TsPlanController {
|
|||||||
private TsPlanService tsPlanService;
|
private TsPlanService tsPlanService;
|
||||||
@Resource
|
@Resource
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
@Resource
|
||||||
|
private TsSourceService tsSourceService;
|
||||||
|
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@Operation(summary = "添加方案")
|
@Operation(summary = "添加方案")
|
||||||
@ -45,9 +51,51 @@ public class TsPlanController {
|
|||||||
// 获取当前登录用户ID
|
// 获取当前登录用户ID
|
||||||
tsPlan.setCreatedBy(StpUtil.getLoginIdAsString());
|
tsPlan.setCreatedBy(StpUtil.getLoginIdAsString());
|
||||||
tsPlanService.save(tsPlan);
|
tsPlanService.save(tsPlan);
|
||||||
|
// 获取最新得到的方案ID
|
||||||
|
String tsPlanId = tsPlan.getId();
|
||||||
|
// 添加方案之后、新增默认资源
|
||||||
|
createSourceIfNotExists("倾斜模型", "directory", null, 0, 1, tsPlanId);
|
||||||
|
createSourceIfNotExists("人工模型", "directory", null, 0, 1, tsPlanId);
|
||||||
|
createSourceIfNotExists("卫星底图", "directory", null, 0, 1, tsPlanId);
|
||||||
|
createSourceIfNotExists("地形", "directory", null, 0, 1, tsPlanId);
|
||||||
|
// 创建"在线图源"目录及其子资源
|
||||||
|
TsSource onlineSource = createSourceIfNotExists("在线图源", "directory", null, 0, 1, tsPlanId);
|
||||||
|
if (onlineSource != null) {
|
||||||
|
String onlineSourceId = onlineSource.getId();
|
||||||
|
createSourceIfNotExists("卫星图", "arcgisWximagery", onlineSourceId, 0, 1, tsPlanId);
|
||||||
|
createSourceIfNotExists("暗黑地图", "arcgisBlueImagery", onlineSourceId, 0, 1, tsPlanId);
|
||||||
|
createSourceIfNotExists("路网图", "gdlwImagery", onlineSourceId, 0, 1, tsPlanId);
|
||||||
|
createSourceIfNotExists("矢量图", "gdslImagery", onlineSourceId, 0, 1, tsPlanId);
|
||||||
|
}
|
||||||
return ApiResponse.success(null);
|
return ApiResponse.success(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TsSource createSourceIfNotExists(String sourceName, String sourceType, String parentId, int treeIndex, int isShow, String tsPlanId) {
|
||||||
|
// 检查资源是否已存在(通过名称和父ID组合判断唯一性)
|
||||||
|
TsSource existingSource = tsSourceService.getOne(new LambdaQueryWrapper<TsSource>()
|
||||||
|
.eq(TsSource::getSourceName, sourceName)
|
||||||
|
.eq(parentId != null, TsSource::getParentId, parentId)
|
||||||
|
.isNull(parentId == null, TsSource::getParentId));
|
||||||
|
if (existingSource != null) {
|
||||||
|
return existingSource;
|
||||||
|
}
|
||||||
|
// 不存在则创建新资源
|
||||||
|
try {
|
||||||
|
TsSource newSource = new TsSource();
|
||||||
|
newSource.setId(cn.hutool.core.lang.UUID.fastUUID().toString(true));
|
||||||
|
newSource.setPlanId(tsPlanId);
|
||||||
|
newSource.setSourceName(sourceName);
|
||||||
|
newSource.setSourceType(sourceType);
|
||||||
|
newSource.setParentId(parentId);
|
||||||
|
newSource.setTreeIndex(treeIndex);
|
||||||
|
newSource.setIsShow(isShow);
|
||||||
|
tsSourceService.save(newSource);
|
||||||
|
return newSource;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "删除方案")
|
@Operation(summary = "删除方案")
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public ApiResponse delete(@Parameter(description = "态势方案ID") @RequestParam(required = true) String id) {
|
public ApiResponse delete(@Parameter(description = "态势方案ID") @RequestParam(required = true) String id) {
|
||||||
@ -73,10 +121,10 @@ public class TsPlanController {
|
|||||||
|
|
||||||
@Operation(summary = "查询所有方案")
|
@Operation(summary = "查询所有方案")
|
||||||
@PostMapping("/list")
|
@PostMapping("/list")
|
||||||
public ApiResponse list(@Parameter(description = "分页数量") @RequestParam Integer pageNum,
|
public ApiResponse list(@Parameter(description = "分页数量") @RequestParam(defaultValue = "1") Integer pageNum,
|
||||||
@Parameter(description = "分页大小") @RequestParam Integer pageSize,
|
@Parameter(description = "分页大小") @RequestParam(defaultValue = "10") Integer pageSize,
|
||||||
@Parameter(description = "方案名称") @RequestParam(required = false) String name,
|
@Parameter(description = "方案名称") @RequestParam(required = false) String name,
|
||||||
@Parameter(description = "用户名称") @RequestParam(required = false) String username,
|
@Parameter(description = "创建人昵称") @RequestParam(required = false) String nickname,
|
||||||
@Parameter(description = "开始时间") @RequestParam(required = false) String startTime,
|
@Parameter(description = "开始时间") @RequestParam(required = false) String startTime,
|
||||||
@Parameter(description = "结束时间") @RequestParam(required = false) String endTime) {
|
@Parameter(description = "结束时间") @RequestParam(required = false) String endTime) {
|
||||||
LambdaQueryWrapper<TsPlan> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<TsPlan> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
@ -86,87 +134,66 @@ public class TsPlanController {
|
|||||||
queryWrapper.like(TsPlan::getName, name);
|
queryWrapper.like(TsPlan::getName, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户名查询
|
// 创建人昵称模糊查询
|
||||||
if (StringUtils.isNotBlank(username)) {
|
if (StringUtils.isNotBlank(nickname)) {
|
||||||
LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.in(TsPlan::getCreatedBy,
|
||||||
userQueryWrapper.like(User::getUsername, username);
|
new LambdaQueryWrapper<User>()
|
||||||
List<User> userList = userService.list(userQueryWrapper);
|
.select(User::getId)
|
||||||
|
.like(User::getNickname, nickname)
|
||||||
// 判断列表是否为空
|
);
|
||||||
if (userList.isEmpty()) {
|
|
||||||
// 无匹配用户、直接返回空分页结果
|
|
||||||
Page<TsPlan> emptyPage = new Page<>(pageNum, pageSize);
|
|
||||||
emptyPage.setTotal(0);
|
|
||||||
emptyPage.setRecords(Collections.emptyList());
|
|
||||||
return ApiResponse.success(emptyPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提取用户 ID 列表(确保类型匹配)
|
|
||||||
List<String> userIdList = userList.stream()
|
|
||||||
.map(User::getId)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
// 若 ID 列表为空,也返回空结果
|
|
||||||
if (userIdList.isEmpty()) {
|
|
||||||
Page<TsPlan> emptyPage = new Page<>(pageNum, pageSize);
|
|
||||||
emptyPage.setTotal(0);
|
|
||||||
emptyPage.setRecords(Collections.emptyList());
|
|
||||||
return ApiResponse.success(emptyPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
queryWrapper.in(TsPlan::getCreatedBy, userIdList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 时间条件优化
|
// 时间范围查询
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
if (StringUtils.isNotBlank(startTime)) {
|
try {
|
||||||
try {
|
if (StringUtils.isNotBlank(startTime)) {
|
||||||
LocalDateTime start = LocalDateTime.parse(startTime, formatter);
|
LocalDateTime start = LocalDateTime.parse(startTime, formatter);
|
||||||
queryWrapper.ge(TsPlan::getCreatedAt, start);
|
queryWrapper.ge(TsPlan::getCreatedAt, start);
|
||||||
} catch (DateTimeException e) {
|
|
||||||
return ApiResponse.failure("开始时间格式错误,需为 yyyy-MM-dd HH:mm:ss");
|
|
||||||
}
|
}
|
||||||
}
|
if (StringUtils.isNotBlank(endTime)) {
|
||||||
if (StringUtils.isNotBlank(endTime)) {
|
|
||||||
try {
|
|
||||||
LocalDateTime end = LocalDateTime.parse(endTime, formatter);
|
LocalDateTime end = LocalDateTime.parse(endTime, formatter);
|
||||||
queryWrapper.le(TsPlan::getCreatedAt, end);
|
queryWrapper.le(TsPlan::getCreatedAt, end);
|
||||||
} catch (DateTimeException e) {
|
|
||||||
return ApiResponse.failure("结束时间格式错误,需为 yyyy-MM-dd HH:mm:ss");
|
|
||||||
}
|
}
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
return ApiResponse.failure("时间格式错误、需为 yyyy-MM-dd HH:mm:ss");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页查询方案
|
// 执行分页查询
|
||||||
Page<TsPlan> page = tsPlanService.page(new Page<>(pageNum, pageSize), queryWrapper);
|
Page<TsPlan> page = tsPlanService.page(new Page<>(pageNum, pageSize), queryWrapper);
|
||||||
|
|
||||||
// 优化用户名查询
|
// 关联查询用户信息并封装结果
|
||||||
if (!page.getRecords().isEmpty()) {
|
if (!page.getRecords().isEmpty()) {
|
||||||
// 提取所有创建人 ID
|
|
||||||
List<String> creatorIds = page.getRecords().stream()
|
List<String> creatorIds = page.getRecords().stream()
|
||||||
.map(TsPlan::getCreatedBy)
|
.map(TsPlan::getCreatedBy)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.distinct()
|
.distinct()
|
||||||
.toList();
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// 批量查询用户
|
|
||||||
if (!creatorIds.isEmpty()) {
|
if (!creatorIds.isEmpty()) {
|
||||||
List<User> creators = userService.listByIds(creatorIds);
|
List<User> creators = userService.listByIds(creatorIds);
|
||||||
// 构建 ID -> 昵称映射
|
|
||||||
Map<String, String> creatorNicknameMap = creators.stream()
|
Map<String, String> creatorNicknameMap = creators.stream()
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
User::getId,
|
User::getId,
|
||||||
User::getNickname,
|
user -> user.getNickname() != null ? user.getNickname() : "未知昵称",
|
||||||
(k1, k2) -> k1));
|
(k1, k2) -> k1
|
||||||
|
));
|
||||||
|
|
||||||
// 填充昵称
|
|
||||||
page.getRecords().forEach(plan -> {
|
page.getRecords().forEach(plan -> {
|
||||||
String nickname = creatorNicknameMap.getOrDefault(plan.getCreatedBy(), "未知用户");
|
plan.setCreatedBy(creatorNicknameMap.getOrDefault(plan.getCreatedBy(), "未知用户"));
|
||||||
plan.setCreatedBy(nickname);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiResponse.success(page);
|
return ApiResponse.success(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽取创建空分页结果的方法
|
||||||
|
*/
|
||||||
|
private Page<TsPlan> createEmptyPage(Integer pageNum, Integer pageSize) {
|
||||||
|
Page<TsPlan> emptyPage = new Page<>(pageNum, pageSize);
|
||||||
|
emptyPage.setTotal(0);
|
||||||
|
emptyPage.setRecords(Collections.emptyList());
|
||||||
|
return emptyPage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import com.yj.earth.business.service.TsSourceService;
|
|||||||
import com.yj.earth.common.util.ApiResponse;
|
import com.yj.earth.common.util.ApiResponse;
|
||||||
import com.yj.earth.common.util.JsonUtil;
|
import com.yj.earth.common.util.JsonUtil;
|
||||||
import com.yj.earth.common.util.MapUtil;
|
import com.yj.earth.common.util.MapUtil;
|
||||||
|
import com.yj.earth.dto.tsPlan.BatchUpdateShowStatusDto;
|
||||||
import com.yj.earth.dto.tsSource.AddTsModelSourceDto;
|
import com.yj.earth.dto.tsSource.AddTsModelSourceDto;
|
||||||
import com.yj.earth.dto.tsSource.AddTsSourceDto;
|
import com.yj.earth.dto.tsSource.AddTsSourceDto;
|
||||||
import com.yj.earth.dto.tsSource.UpdateTsSourceDto;
|
import com.yj.earth.dto.tsSource.UpdateTsSourceDto;
|
||||||
@ -54,6 +55,19 @@ public class TsSourceController {
|
|||||||
return ApiResponse.success(null);
|
return ApiResponse.success(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "批量修改资源显示状态")
|
||||||
|
@PostMapping("/batchUpdateShowStatus")
|
||||||
|
public ApiResponse batchUpdateShowStatus(@RequestBody List<BatchUpdateShowStatusDto> batchUpdateShowStatusDtoList) {
|
||||||
|
for (BatchUpdateShowStatusDto batchUpdateShowStatusDto : batchUpdateShowStatusDtoList) {
|
||||||
|
LambdaQueryWrapper<TsSource> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
TsSource tsSource = new TsSource();
|
||||||
|
tsSource.setId(batchUpdateShowStatusDto.getId());
|
||||||
|
tsSource.setIsShow(batchUpdateShowStatusDto.getShow());
|
||||||
|
tsSourceService.updateById(tsSource);
|
||||||
|
}
|
||||||
|
return ApiResponse.success(null);
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "查询某个方案下的态势资源")
|
@Operation(summary = "查询某个方案下的态势资源")
|
||||||
@PostMapping("/query")
|
@PostMapping("/query")
|
||||||
public ApiResponse query(@Parameter(description = "态势方案ID") @RequestParam(required = true) String id) {
|
public ApiResponse query(@Parameter(description = "态势方案ID") @RequestParam(required = true) String id) {
|
||||||
|
|||||||
@ -51,6 +51,6 @@ public class Source implements Serializable {
|
|||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
@Schema(description = "更新时间")
|
@Schema(description = "更新时间")
|
||||||
@TableField(fill = FieldFill.UPDATE)
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,8 @@ public interface SourceService extends IService<Source> {
|
|||||||
|
|
||||||
String fetchCltDetail(String sourceId);
|
String fetchCltDetail(String sourceId);
|
||||||
|
|
||||||
|
String fetchJsonDetail(String sourceId);
|
||||||
|
|
||||||
String fetchMbtilesDetail(String sourceId);
|
String fetchMbtilesDetail(String sourceId);
|
||||||
|
|
||||||
String fetchPakDetail(String sourceId);
|
String fetchPakDetail(String sourceId);
|
||||||
|
|||||||
@ -61,6 +61,7 @@ public class SourceServiceImpl extends ServiceImpl<SourceMapper, Source> impleme
|
|||||||
detailFetchers.put("clt", this::fetchCltDetail);
|
detailFetchers.put("clt", this::fetchCltDetail);
|
||||||
detailFetchers.put("mbtiles", this::fetchMbtilesDetail);
|
detailFetchers.put("mbtiles", this::fetchMbtilesDetail);
|
||||||
detailFetchers.put("pak", this::fetchPakDetail);
|
detailFetchers.put("pak", this::fetchPakDetail);
|
||||||
|
detailFetchers.put("json", this::fetchJsonDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,6 +157,15 @@ public class SourceServiceImpl extends ServiceImpl<SourceMapper, Source> impleme
|
|||||||
return HttpUtil.doGet(url);
|
return HttpUtil.doGet(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 JSON 类型资源详情
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String fetchJsonDetail(String sourceId) {
|
||||||
|
String url = buildSdkUrl("/data/clt/json/detail/" + sourceId);
|
||||||
|
return HttpUtil.doGet(url);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 MBTiles 类型资源详情
|
* 获取 MBTiles 类型资源详情
|
||||||
*/
|
*/
|
||||||
@ -199,12 +209,14 @@ public class SourceServiceImpl extends ServiceImpl<SourceMapper, Source> impleme
|
|||||||
return resultMap;
|
return resultMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建用于计算总数的查询条件(始终排除directory类型)
|
// 创建用于计算总数的查询条件
|
||||||
LambdaQueryWrapper<Source> countQueryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<Source> countQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
countQueryWrapper.ne(Source::getSourceType, "directory");
|
countQueryWrapper.ne(Source::getSourceType, "directory");
|
||||||
|
|
||||||
// 构建资源查询条件
|
// 构建资源查询条件
|
||||||
LambdaQueryWrapper<Source> sourceQueryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<Source> sourceQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
// 排序字段
|
||||||
|
sourceQueryWrapper.orderByDesc(Source::getUpdatedAt);
|
||||||
|
|
||||||
// 公共查询条件
|
// 公共查询条件
|
||||||
if (sourceType != null) {
|
if (sourceType != null) {
|
||||||
@ -263,7 +275,6 @@ public class SourceServiceImpl extends ServiceImpl<SourceMapper, Source> impleme
|
|||||||
// 不分页: 获取全部数据(包含所有类型)和总数(排除directory)
|
// 不分页: 获取全部数据(包含所有类型)和总数(排除directory)
|
||||||
List<Source> sourceList = sourceService.list(sourceQueryWrapper);
|
List<Source> sourceList = sourceService.list(sourceQueryWrapper);
|
||||||
long total = sourceService.count(countQueryWrapper);
|
long total = sourceService.count(countQueryWrapper);
|
||||||
|
|
||||||
resultMap.put("list", sourceList);
|
resultMap.put("list", sourceList);
|
||||||
resultMap.put("total", total);
|
resultMap.put("total", total);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,7 +121,7 @@ public class SQLiteUtil {
|
|||||||
try {
|
try {
|
||||||
dataSource.close();
|
dataSource.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
System.err.println("关闭SQLite数据源失败: " + e.getMessage());
|
System.err.println("关闭SQLite: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 清理缓存(避免内存泄漏)
|
// 清理缓存(避免内存泄漏)
|
||||||
@ -199,7 +199,7 @@ public class SQLiteUtil {
|
|||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
// 异常时关闭当前数据源(避免后续请求使用异常连接)
|
// 异常时关闭当前数据源(避免后续请求使用异常连接)
|
||||||
closeDataSource(dbFilePath);
|
closeDataSource(dbFilePath);
|
||||||
throw new SQLException("执行查询失败(SQL: " + sql + ")", e);
|
throw new SQLException("请检查文件是否存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultList;
|
return resultList;
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.yj.earth.dto.tsPlan;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class BatchUpdateShowStatusDto {
|
||||||
|
@Schema(description = "资源ID列表")
|
||||||
|
private String id;
|
||||||
|
@Schema(description = "显示状态")
|
||||||
|
private Integer show;
|
||||||
|
}
|
||||||
@ -54,6 +54,22 @@ public class Path {
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class CustomView {
|
public static class CustomView {
|
||||||
|
private AttackArrow.CustomView.Orientation orientation;
|
||||||
|
private AttackArrow.CustomView.RelativePosition relativePosition;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Orientation {
|
||||||
|
private double heading;
|
||||||
|
private double pitch;
|
||||||
|
private double roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class RelativePosition {
|
||||||
|
private double lng;
|
||||||
|
private double lat;
|
||||||
|
private double alt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import java.util.List;
|
|||||||
@SourceType("roam")
|
@SourceType("roam")
|
||||||
public class Roam {
|
public class Roam {
|
||||||
private String name;
|
private String name;
|
||||||
|
private String defaultTime;
|
||||||
|
private String totalTime;
|
||||||
private List<Point> points;
|
private List<Point> points;
|
||||||
private String repeat;
|
private String repeat;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user