2025-09-26 13:46:54 +08:00
|
|
|
|
package com.yj.earth.business.controller;
|
|
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.io.FileUtil;
|
|
|
|
|
|
import cn.hutool.core.lang.UUID;
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
|
import com.yj.earth.annotation.CheckAuth;
|
2025-11-24 09:50:57 +08:00
|
|
|
|
import com.yj.earth.business.domain.*;
|
2025-09-30 09:55:07 +08:00
|
|
|
|
import com.yj.earth.business.service.MilitaryLibraryService;
|
2025-11-24 09:50:57 +08:00
|
|
|
|
import com.yj.earth.business.service.SourceService;
|
2025-09-26 13:46:54 +08:00
|
|
|
|
import com.yj.earth.common.util.ApiResponse;
|
2025-09-29 17:34:21 +08:00
|
|
|
|
import com.yj.earth.common.util.FileCommonUtil;
|
2025-11-24 09:50:57 +08:00
|
|
|
|
import com.yj.earth.common.util.JsonUtil;
|
2025-09-26 13:46:54 +08:00
|
|
|
|
import com.yj.earth.common.util.SQLiteUtil;
|
2025-09-30 09:55:07 +08:00
|
|
|
|
import com.yj.earth.dto.militaryLibrary.AddMilitaryTypeDto;
|
|
|
|
|
|
import com.yj.earth.dto.militaryLibrary.CreateMilitaryLibraryDto;
|
|
|
|
|
|
import com.yj.earth.dto.militaryLibrary.DragMilitaryTypeDto;
|
|
|
|
|
|
import com.yj.earth.dto.militaryLibrary.UpdateMilitaryTypeNameDto;
|
2025-11-24 09:50:57 +08:00
|
|
|
|
import com.yj.earth.params.MilitaryParam;
|
|
|
|
|
|
import com.yj.earth.params.ModelParam;
|
2025-09-29 17:34:21 +08:00
|
|
|
|
import com.yj.earth.vo.MilitaryDataVo;
|
2025-09-30 09:55:07 +08:00
|
|
|
|
import com.yj.earth.vo.MilitaryTypeVo;
|
|
|
|
|
|
import com.yj.earth.vo.MilitaryVo;
|
2025-09-26 13:46:54 +08:00
|
|
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
|
|
|
|
import io.swagger.v3.oas.annotations.Parameter;
|
|
|
|
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
2025-11-24 09:50:57 +08:00
|
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
2025-09-29 17:34:21 +08:00
|
|
|
|
import org.springframework.http.HttpHeaders;
|
|
|
|
|
|
import org.springframework.http.HttpStatus;
|
|
|
|
|
|
import org.springframework.http.MediaType;
|
|
|
|
|
|
import org.springframework.http.ResponseEntity;
|
2025-09-26 13:46:54 +08:00
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
|
import java.io.IOException;
|
2025-09-29 17:34:21 +08:00
|
|
|
|
import java.net.URLEncoder;
|
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
2025-11-20 15:10:08 +08:00
|
|
|
|
import java.nio.file.Files;
|
2025-09-26 13:46:54 +08:00
|
|
|
|
import java.sql.SQLException;
|
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
|
import java.util.ArrayList;
|
2025-09-29 17:34:21 +08:00
|
|
|
|
import java.util.Comparator;
|
2025-09-26 13:46:54 +08:00
|
|
|
|
import java.util.List;
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
2025-09-30 10:14:40 +08:00
|
|
|
|
@Tag(name = "军标数据管理")
|
2025-11-19 16:10:25 +08:00
|
|
|
|
|
2025-09-26 13:46:54 +08:00
|
|
|
|
@RestController
|
|
|
|
|
|
@RequestMapping("/militaryLibrary")
|
|
|
|
|
|
public class MilitaryLibraryController {
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
2025-09-26 13:46:54 +08:00
|
|
|
|
@Resource
|
|
|
|
|
|
private MilitaryLibraryService militaryLibraryService;
|
2025-11-24 09:50:57 +08:00
|
|
|
|
@Resource
|
|
|
|
|
|
private SourceService sourceService;
|
|
|
|
|
|
@Value("${server.host}")
|
|
|
|
|
|
private String serverHost;
|
|
|
|
|
|
@Value("${server.port}")
|
|
|
|
|
|
private int serverPort;
|
2025-09-26 13:46:54 +08:00
|
|
|
|
|
|
|
|
|
|
@Operation(summary = "创建军标库")
|
|
|
|
|
|
@PostMapping("/createMilitaryLibrary")
|
2025-09-29 17:34:21 +08:00
|
|
|
|
public ApiResponse createMilitaryLibrary(@RequestBody CreateMilitaryLibraryDto createDto) {
|
2025-09-26 13:46:54 +08:00
|
|
|
|
try {
|
2025-09-29 17:34:21 +08:00
|
|
|
|
// 参数校验与路径处理
|
|
|
|
|
|
String folderPath = createDto.getPath();
|
|
|
|
|
|
String libraryName = createDto.getName();
|
|
|
|
|
|
if (!StringUtils.hasText(folderPath) || !StringUtils.hasText(libraryName)) {
|
|
|
|
|
|
return ApiResponse.failure("路径和名称不能为空");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构建完整军标库文件路径(SQLite文件)
|
2025-09-26 13:46:54 +08:00
|
|
|
|
File parentDir = new File(folderPath);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
File militaryFile = new File(parentDir, libraryName);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
String militaryPath = militaryFile.getAbsolutePath().replace("\\", "/");
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 父目录不存在则创建
|
2025-09-26 13:46:54 +08:00
|
|
|
|
if (!parentDir.exists()) {
|
|
|
|
|
|
boolean mkdirsSuccess = parentDir.mkdirs();
|
|
|
|
|
|
if (!mkdirsSuccess) {
|
2025-11-25 14:27:10 +08:00
|
|
|
|
return ApiResponse.failure("创建父目录失败: " + folderPath);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 校验军标库文件是否已存在
|
2025-09-26 13:46:54 +08:00
|
|
|
|
if (militaryFile.exists()) {
|
|
|
|
|
|
if (militaryFile.isDirectory()) {
|
2025-11-25 14:27:10 +08:00
|
|
|
|
return ApiResponse.failure("同名目录已存在、无法创建文件: " + militaryPath);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
2025-11-25 14:27:10 +08:00
|
|
|
|
return ApiResponse.failure("军标库文件已存在: " + militaryPath);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 创建SQLite文件
|
|
|
|
|
|
boolean createFileSuccess = militaryFile.createNewFile();
|
|
|
|
|
|
if (!createFileSuccess) {
|
2025-11-25 14:27:10 +08:00
|
|
|
|
return ApiResponse.failure("创建军标库文件失败: " + militaryPath);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 初始化军标库表结构
|
2025-09-26 13:46:54 +08:00
|
|
|
|
SQLiteUtil.initializationMilitary(militaryPath);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
// 添加军标库配置到数据库
|
|
|
|
|
|
addMilitaryLibrary(militaryPath);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
return ApiResponse.success(null);
|
|
|
|
|
|
} catch (Exception e) {
|
2025-11-25 14:27:10 +08:00
|
|
|
|
return ApiResponse.failure("创建军标库失败: " + e.getMessage());
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Operation(summary = "导入军标库")
|
|
|
|
|
|
@PostMapping("/importMilitaryLibrary")
|
2025-09-29 17:34:21 +08:00
|
|
|
|
public ApiResponse importMilitaryLibrary(
|
|
|
|
|
|
@RequestParam("militaryPath") @Parameter(description = "军标库SQLite文件路径") String militaryPath) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 校验路径是否存在
|
|
|
|
|
|
File militaryFile = new File(militaryPath);
|
|
|
|
|
|
if (!militaryFile.exists() || !militaryFile.isFile()) {
|
2025-11-25 14:27:10 +08:00
|
|
|
|
return ApiResponse.failure("军标库文件不存在: " + militaryPath);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 添加到配置表并启用
|
|
|
|
|
|
addMilitaryLibrary(militaryPath);
|
|
|
|
|
|
return ApiResponse.success(null);
|
|
|
|
|
|
} catch (Exception e) {
|
2025-11-25 14:27:10 +08:00
|
|
|
|
return ApiResponse.failure("导入军标库失败: " + e.getMessage());
|
2025-09-29 17:34:21 +08:00
|
|
|
|
}
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Operation(summary = "添加军标类型")
|
|
|
|
|
|
@PostMapping("/addMilitaryType")
|
2025-09-29 17:34:21 +08:00
|
|
|
|
public ApiResponse addMilitaryType(@RequestBody AddMilitaryTypeDto addDto) throws SQLException, IllegalAccessException, InstantiationException {
|
|
|
|
|
|
// 获取当前启用的军标库路径
|
2025-09-26 13:46:54 +08:00
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return ApiResponse.failure("请先创建或导入军标库");
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 校验父级类型(若有)
|
|
|
|
|
|
String parentId = addDto.getParentId();
|
|
|
|
|
|
if (StringUtils.hasText(parentId)) {
|
|
|
|
|
|
String checkParentSql = "SELECT id FROM military_type WHERE id = ?";
|
|
|
|
|
|
List<Object> parentParams = new ArrayList<>();
|
|
|
|
|
|
parentParams.add(parentId);
|
|
|
|
|
|
MilitaryType parentType = SQLiteUtil.queryForObject(
|
|
|
|
|
|
militaryPath, checkParentSql, parentParams, MilitaryType.class
|
|
|
|
|
|
);
|
|
|
|
|
|
if (parentType == null) {
|
2025-11-25 14:27:10 +08:00
|
|
|
|
return ApiResponse.failure("父级军标类型不存在: " + parentId);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 插入军标类型
|
|
|
|
|
|
String insertSql = "INSERT INTO military_type " +
|
2025-09-26 13:46:54 +08:00
|
|
|
|
"(id, name, parent_id, tree_index, created_at) " +
|
|
|
|
|
|
"VALUES (?, ?, ?, ?, ?)";
|
|
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(UUID.fastUUID().toString(true));
|
2025-09-29 17:34:21 +08:00
|
|
|
|
params.add(addDto.getName());
|
|
|
|
|
|
params.add(parentId);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
params.add(0);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
params.add(LocalDateTime.now().toString());
|
|
|
|
|
|
SQLiteUtil.executeUpdate(militaryPath, insertSql, params);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
return ApiResponse.success(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
@Operation(summary = "修改军标类型名称")
|
|
|
|
|
|
@PostMapping("/updateMilitaryTypeName")
|
|
|
|
|
|
public ApiResponse updateMilitaryTypeName(@RequestBody UpdateMilitaryTypeNameDto updateDto)
|
|
|
|
|
|
throws SQLException {
|
2025-09-26 13:46:54 +08:00
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return ApiResponse.failure("请先创建或导入军标库");
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 执行更新
|
|
|
|
|
|
String updateSql = "UPDATE military_type SET name = ?, updated_at = ? WHERE id = ?";
|
2025-09-26 13:46:54 +08:00
|
|
|
|
List<Object> params = new ArrayList<>();
|
2025-09-29 17:34:21 +08:00
|
|
|
|
params.add(updateDto.getName());
|
|
|
|
|
|
params.add(LocalDateTime.now().toString());
|
|
|
|
|
|
params.add(updateDto.getId());
|
|
|
|
|
|
SQLiteUtil.executeUpdate(militaryPath, updateSql, params);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
return ApiResponse.success(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
@Operation(summary = "删除军标类型")
|
|
|
|
|
|
@PostMapping("/deleteMilitaryType")
|
|
|
|
|
|
public ApiResponse deleteMilitaryType(
|
|
|
|
|
|
@RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId)
|
|
|
|
|
|
throws SQLException {
|
2025-09-26 13:46:54 +08:00
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return ApiResponse.failure("请先创建或导入军标库");
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 执行删除
|
|
|
|
|
|
String deleteSql = "DELETE FROM military_type WHERE id = ?";
|
2025-09-26 13:46:54 +08:00
|
|
|
|
List<Object> params = new ArrayList<>();
|
2025-09-29 17:34:21 +08:00
|
|
|
|
params.add(typeId);
|
|
|
|
|
|
|
|
|
|
|
|
SQLiteUtil.executeUpdate(militaryPath, deleteSql, params);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
return ApiResponse.success(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
@Operation(summary = "军标类型树形列表")
|
|
|
|
|
|
@GetMapping("/militaryTypeTree")
|
2025-09-26 13:46:54 +08:00
|
|
|
|
public ApiResponse militaryTypeTree() throws SQLException, IllegalAccessException, InstantiationException {
|
2025-09-29 17:34:21 +08:00
|
|
|
|
List<MilitaryTypeVo> treeList = militaryTypeList();
|
2025-09-26 13:46:54 +08:00
|
|
|
|
return ApiResponse.success(treeList);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
@Operation(summary = "添加军标文件")
|
|
|
|
|
|
@PostMapping("/addMilitaryFile")
|
2025-11-20 15:10:08 +08:00
|
|
|
|
public ApiResponse addMilitaryFile(@RequestParam("filePaths") List<String> filePaths,
|
|
|
|
|
|
@RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId) throws IOException, SQLException {
|
2025-09-26 13:46:54 +08:00
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
|
2025-11-20 15:10:08 +08:00
|
|
|
|
// 循环处理每个绝对路径对应的文件
|
|
|
|
|
|
for (String filePath : filePaths) {
|
|
|
|
|
|
File file = new File(filePath);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 解析文件名与后缀
|
2025-11-20 15:10:08 +08:00
|
|
|
|
String originalFileName = file.getName();
|
2025-09-29 17:34:21 +08:00
|
|
|
|
String fileSuffix = FileUtil.extName(originalFileName);
|
|
|
|
|
|
String fileNameWithoutSuffix = FileUtil.mainName(originalFileName);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
// 插入军标数据
|
|
|
|
|
|
String insertSql = "INSERT INTO military " +
|
|
|
|
|
|
"(id, military_type_id, military_name, military_type, military_data, created_at) " +
|
2025-09-26 13:46:54 +08:00
|
|
|
|
"VALUES (?, ?, ?, ?, ?, ?)";
|
|
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(UUID.fastUUID().toString(true));
|
2025-09-29 17:34:21 +08:00
|
|
|
|
params.add(typeId);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
params.add(fileNameWithoutSuffix);
|
|
|
|
|
|
params.add(fileSuffix);
|
2025-11-20 15:10:08 +08:00
|
|
|
|
params.add(Files.readAllBytes(file.toPath()));
|
2025-09-29 17:34:21 +08:00
|
|
|
|
params.add(LocalDateTime.now().toString());
|
2025-09-26 13:46:54 +08:00
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
SQLiteUtil.executeUpdate(militaryPath, insertSql, params);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ApiResponse.success(null);
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
@Operation(summary = "获取军标文件数据")
|
|
|
|
|
|
@GetMapping("/data/military/{militaryId}/{fileSuffix}")
|
|
|
|
|
|
public ResponseEntity<byte[]> getMilitaryData(@PathVariable("militaryId") @Parameter(description = "军标ID") String militaryId, @PathVariable("fileSuffix") @Parameter(description = "军标文件后缀") String fileSuffix) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return ResponseEntity.notFound().build();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 查询军标二进制数据
|
|
|
|
|
|
String querySql = "SELECT military_name, military_data FROM military WHERE id = ?";
|
|
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(militaryId);
|
|
|
|
|
|
MilitaryDataVo dataVo = SQLiteUtil.queryForObject(
|
|
|
|
|
|
militaryPath, querySql, params, MilitaryDataVo.class
|
|
|
|
|
|
);
|
|
|
|
|
|
if (dataVo == null || dataVo.getMilitaryData() == null) {
|
|
|
|
|
|
return ResponseEntity.notFound().build();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 构建响应头【支持中文文件名+预览】
|
|
|
|
|
|
String originalFileName = dataVo.getMilitaryName() + "." + fileSuffix;
|
|
|
|
|
|
String encodedFileName = URLEncoder.encode(originalFileName, StandardCharsets.UTF_8.name());
|
|
|
|
|
|
MediaType contentType = FileCommonUtil.getImageMediaType(fileSuffix);
|
|
|
|
|
|
|
|
|
|
|
|
return ResponseEntity.ok()
|
|
|
|
|
|
.contentType(contentType)
|
|
|
|
|
|
.header(HttpHeaders.CONTENT_DISPOSITION,
|
|
|
|
|
|
"inline; filename=\"" + encodedFileName + "\"")
|
|
|
|
|
|
.body(dataVo.getMilitaryData());
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Operation(summary = "根据类型查询军标列表")
|
2025-09-26 13:46:54 +08:00
|
|
|
|
@PostMapping("/militaryList")
|
2025-09-29 17:34:21 +08:00
|
|
|
|
public ApiResponse getMilitaryList(@RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId) throws SQLException, IllegalAccessException, InstantiationException {
|
2025-09-26 13:46:54 +08:00
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return ApiResponse.failure("请先创建或导入军标库");
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取当前类型及所有子类型ID(递归)
|
|
|
|
|
|
List<String> typeIdList = getMilitaryTypeIdsWithChildren(typeId);
|
|
|
|
|
|
if (typeIdList == null || typeIdList.isEmpty()) {
|
|
|
|
|
|
return ApiResponse.success(new ArrayList<>());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构建IN条件(处理SQL注入风险)
|
|
|
|
|
|
String idsWithQuotes = typeIdList.stream()
|
|
|
|
|
|
.map(id -> "'" + id + "'")
|
|
|
|
|
|
.collect(Collectors.joining(","));
|
|
|
|
|
|
|
|
|
|
|
|
// 多表联查
|
|
|
|
|
|
String querySql = """
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
m.id,
|
|
|
|
|
|
m.military_type_id as militaryTypeId,
|
|
|
|
|
|
m.military_name as militaryName,
|
|
|
|
|
|
m.military_type as militaryType,
|
|
|
|
|
|
m.created_at as createdAt,
|
|
|
|
|
|
m.updated_at as updatedAt,
|
|
|
|
|
|
t.name as militaryTypeName
|
|
|
|
|
|
FROM military m
|
|
|
|
|
|
JOIN military_type t ON m.military_type_id = t.id
|
|
|
|
|
|
WHERE m.military_type_id IN (%s)
|
|
|
|
|
|
ORDER BY m.created_at DESC
|
|
|
|
|
|
""".replace("%s", idsWithQuotes);
|
|
|
|
|
|
|
|
|
|
|
|
// 查询并转换为VO
|
|
|
|
|
|
List<MilitaryVo> militaryVoList = SQLiteUtil.queryForList(
|
|
|
|
|
|
militaryPath, querySql, null, MilitaryVo.class
|
|
|
|
|
|
);
|
|
|
|
|
|
for (MilitaryVo vo : militaryVoList) {
|
|
|
|
|
|
vo.setMilitaryDataUrl("/militaryLibrary/data/military/" + vo.getId() + "/" + vo.getMilitaryType());
|
|
|
|
|
|
}
|
|
|
|
|
|
return ApiResponse.success(militaryVoList);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
@Operation(summary = "更新军标名称")
|
|
|
|
|
|
@PostMapping("/updateMilitaryInfo")
|
|
|
|
|
|
public ApiResponse updateMilitaryInfo(
|
|
|
|
|
|
@RequestParam("militaryId") @Parameter(description = "军标ID") String militaryId,
|
|
|
|
|
|
@RequestParam("militaryName") @Parameter(description = "新军标名称") String militaryName)
|
2025-09-26 13:46:54 +08:00
|
|
|
|
throws SQLException {
|
|
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return ApiResponse.failure("请先创建或导入军标库");
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
String updateSql = "UPDATE military SET military_name = ?, updated_at = ? WHERE id = ?";
|
2025-09-26 13:46:54 +08:00
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(militaryName);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
params.add(LocalDateTime.now().toString());
|
2025-09-26 13:46:54 +08:00
|
|
|
|
params.add(militaryId);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
SQLiteUtil.executeUpdate(militaryPath, updateSql, params);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
return ApiResponse.success(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Operation(summary = "删除军标")
|
|
|
|
|
|
@PostMapping("/deleteMilitary")
|
2025-09-29 17:34:21 +08:00
|
|
|
|
public ApiResponse deleteMilitary(@RequestParam("militaryId") @Parameter(description = "军标ID") String militaryId) throws SQLException {
|
2025-09-26 13:46:54 +08:00
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return ApiResponse.failure("请先创建或导入军标库");
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
2025-11-24 09:50:57 +08:00
|
|
|
|
// 存储被删除的Source ID列表
|
|
|
|
|
|
List<String> deletedSourceIds = new ArrayList<>();
|
|
|
|
|
|
// 获取URL
|
|
|
|
|
|
String MilitaryDataUrlByModelId = getMilitaryDataUrlByModelId(militaryId);
|
|
|
|
|
|
// 查询资源
|
|
|
|
|
|
LambdaQueryWrapper<Source> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
|
// 查询类型为 model 的
|
|
|
|
|
|
queryWrapper.eq(Source::getSourceType, "military");
|
|
|
|
|
|
// 查询列表
|
|
|
|
|
|
List<Source> sourceList = sourceService.list(queryWrapper);
|
|
|
|
|
|
// 遍历数据
|
|
|
|
|
|
for (Source source : sourceList) {
|
|
|
|
|
|
// 取出 params 字段
|
|
|
|
|
|
String dataParams = source.getParams();
|
|
|
|
|
|
if (dataParams != null) {
|
|
|
|
|
|
// 转换为 Model 对象
|
|
|
|
|
|
MilitaryParam militaryParam = JsonUtil.jsonToObject(dataParams, MilitaryParam.class);
|
|
|
|
|
|
if (MilitaryDataUrlByModelId.equals(militaryParam.getUrl())) {
|
|
|
|
|
|
// 删除这个资源
|
|
|
|
|
|
sourceService.removeById(source.getId());
|
|
|
|
|
|
// 添加到被删除的ID列表
|
|
|
|
|
|
deletedSourceIds.add(source.getId());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
// 执行删除
|
|
|
|
|
|
String deleteSql = "DELETE FROM military WHERE id = ?";
|
2025-09-26 13:46:54 +08:00
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(militaryId);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
SQLiteUtil.executeUpdate(militaryPath, deleteSql, params);
|
2025-11-24 09:50:57 +08:00
|
|
|
|
return ApiResponse.success(deletedSourceIds);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
@Operation(summary = "拖动调整军标类型层级")
|
|
|
|
|
|
@PostMapping("/dragMilitaryType")
|
|
|
|
|
|
public ApiResponse dragMilitaryType(@RequestBody List<DragMilitaryTypeDto> dragDtoList)
|
|
|
|
|
|
throws SQLException, IllegalAccessException, InstantiationException {
|
|
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return ApiResponse.failure("请先创建或导入军标库");
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
// 批量更新层级和排序
|
|
|
|
|
|
for (DragMilitaryTypeDto dto : dragDtoList) {
|
|
|
|
|
|
String updateSql = "UPDATE military_type " +
|
|
|
|
|
|
"SET parent_id = ?, tree_index = ?, updated_at = ? " +
|
|
|
|
|
|
"WHERE id = ?";
|
|
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(dto.getParentId());
|
|
|
|
|
|
params.add(dto.getTreeIndex());
|
|
|
|
|
|
params.add(LocalDateTime.now().toString());
|
|
|
|
|
|
params.add(dto.getId());
|
|
|
|
|
|
|
|
|
|
|
|
SQLiteUtil.executeUpdate(militaryPath, updateSql, params);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 返回更新后的树形列表
|
|
|
|
|
|
List<MilitaryTypeVo> treeList = militaryTypeList();
|
|
|
|
|
|
return ApiResponse.success(treeList);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private String getMilitaryLibrary() {
|
|
|
|
|
|
LambdaQueryWrapper<MilitaryLibrary> queryWrapper = new LambdaQueryWrapper<>();
|
2025-09-30 11:29:25 +08:00
|
|
|
|
queryWrapper.eq(MilitaryLibrary::getIsEnable, 1); // 1=启用、0=未启用
|
2025-09-29 17:34:21 +08:00
|
|
|
|
MilitaryLibrary library = militaryLibraryService.getOne(queryWrapper);
|
|
|
|
|
|
return library == null ? null : library.getPath();
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void addMilitaryLibrary(String militaryPath) {
|
2025-09-29 17:34:21 +08:00
|
|
|
|
// 所有已存在的军标库设置为「未启用」
|
|
|
|
|
|
List<MilitaryLibrary> existLibraries = militaryLibraryService.list();
|
|
|
|
|
|
for (MilitaryLibrary library : existLibraries) {
|
|
|
|
|
|
library.setIsEnable(0);
|
|
|
|
|
|
militaryLibraryService.updateById(library);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-30 11:29:25 +08:00
|
|
|
|
// 检查路径是否已存在(存在则启用、不存在则新增)
|
2025-09-26 13:46:54 +08:00
|
|
|
|
LambdaQueryWrapper<MilitaryLibrary> pathWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
|
pathWrapper.eq(MilitaryLibrary::getPath, militaryPath);
|
2025-09-29 17:34:21 +08:00
|
|
|
|
MilitaryLibrary existLibrary = militaryLibraryService.getOne(pathWrapper);
|
|
|
|
|
|
|
|
|
|
|
|
if (existLibrary != null) {
|
|
|
|
|
|
existLibrary.setIsEnable(1);
|
|
|
|
|
|
militaryLibraryService.updateById(existLibrary);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
} else {
|
2025-09-29 17:34:21 +08:00
|
|
|
|
MilitaryLibrary newLibrary = new MilitaryLibrary();
|
|
|
|
|
|
newLibrary.setId(UUID.fastUUID().toString(true));
|
|
|
|
|
|
newLibrary.setPath(militaryPath);
|
|
|
|
|
|
newLibrary.setName(FileUtil.mainName(militaryPath));
|
|
|
|
|
|
newLibrary.setIsEnable(1);
|
|
|
|
|
|
newLibrary.setCreatedAt(LocalDateTime.now());
|
|
|
|
|
|
militaryLibraryService.save(newLibrary);
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-29 17:34:21 +08:00
|
|
|
|
|
|
|
|
|
|
private List<MilitaryTypeVo> militaryTypeList() throws SQLException, IllegalAccessException, InstantiationException {
|
|
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return new ArrayList<>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String querySql = """
|
|
|
|
|
|
SELECT
|
|
|
|
|
|
id, name, parent_id as parentId,
|
|
|
|
|
|
tree_index as treeIndex, created_at as createdAt,
|
|
|
|
|
|
updated_at as updatedAt
|
|
|
|
|
|
FROM military_type
|
|
|
|
|
|
ORDER BY tree_index ASC
|
|
|
|
|
|
""";
|
|
|
|
|
|
List<MilitaryType> typeList = SQLiteUtil.queryForList(militaryPath, querySql, null, MilitaryType.class);
|
|
|
|
|
|
|
|
|
|
|
|
// 构建树形结构
|
|
|
|
|
|
return buildMilitaryTypeTree(typeList);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<MilitaryTypeVo> buildMilitaryTypeTree(List<MilitaryType> typeList) {
|
|
|
|
|
|
// 转换为VO
|
|
|
|
|
|
List<MilitaryTypeVo> voList = typeList.stream()
|
|
|
|
|
|
.map(militaryType -> new MilitaryTypeVo(militaryType)).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
|
|
// 构建ID→VO的映射(方便快速查找父级)
|
|
|
|
|
|
Map<String, MilitaryTypeVo> voMap = voList.stream()
|
|
|
|
|
|
.collect(Collectors.toMap(MilitaryTypeVo::getId, vo -> vo));
|
|
|
|
|
|
|
|
|
|
|
|
// 组装树形结构
|
|
|
|
|
|
List<MilitaryTypeVo> rootList = new ArrayList<>();
|
|
|
|
|
|
for (MilitaryTypeVo vo : voList) {
|
|
|
|
|
|
String parentId = vo.getParentId();
|
|
|
|
|
|
if (parentId == null || parentId.isEmpty()) {
|
|
|
|
|
|
rootList.add(vo);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
MilitaryTypeVo parentVo = voMap.get(parentId);
|
|
|
|
|
|
if (parentVo != null) {
|
|
|
|
|
|
parentVo.getChildren().add(vo);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 排序
|
|
|
|
|
|
rootList.sort(Comparator.comparingInt(MilitaryTypeVo::getTreeIndex));
|
|
|
|
|
|
sortMilitaryTypeChildren(rootList);
|
|
|
|
|
|
|
|
|
|
|
|
return rootList;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void sortMilitaryTypeChildren(List<MilitaryTypeVo> voList) {
|
|
|
|
|
|
if (voList == null || voList.isEmpty()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 排序当前层级
|
|
|
|
|
|
voList.sort(Comparator.comparingInt(MilitaryTypeVo::getTreeIndex));
|
|
|
|
|
|
// 递归排序子层级
|
|
|
|
|
|
for (MilitaryTypeVo vo : voList) {
|
|
|
|
|
|
sortMilitaryTypeChildren(vo.getChildren());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<String> getMilitaryTypeIdsWithChildren(String typeId)
|
|
|
|
|
|
throws SQLException, IllegalAccessException, InstantiationException {
|
|
|
|
|
|
List<String> idList = new ArrayList<>();
|
|
|
|
|
|
if (!StringUtils.hasText(typeId)) {
|
|
|
|
|
|
return idList;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String militaryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryPath == null) {
|
|
|
|
|
|
return idList;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 校验类型是否存在
|
|
|
|
|
|
if (!isMilitaryTypeExist(militaryPath, typeId)) {
|
|
|
|
|
|
return idList;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 递归收集ID(包含自身)
|
|
|
|
|
|
recursiveGetMilitaryTypeChildren(militaryPath, typeId, idList);
|
|
|
|
|
|
return idList;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void recursiveGetMilitaryTypeChildren(String militaryPath, String currentId, List<String> idList)
|
|
|
|
|
|
throws SQLException, IllegalAccessException, InstantiationException {
|
|
|
|
|
|
// 先添加当前ID
|
|
|
|
|
|
idList.add(currentId);
|
|
|
|
|
|
|
|
|
|
|
|
// 查询直接子类型
|
|
|
|
|
|
String querySql = "SELECT id FROM military_type WHERE parent_id = ? ORDER BY tree_index ASC";
|
|
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(currentId);
|
|
|
|
|
|
List<MilitaryType> childList = SQLiteUtil.queryForList(
|
|
|
|
|
|
militaryPath, querySql, params, MilitaryType.class
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 递归查询子类型的子类型
|
|
|
|
|
|
if (childList != null && !childList.isEmpty()) {
|
|
|
|
|
|
for (MilitaryType child : childList) {
|
|
|
|
|
|
recursiveGetMilitaryTypeChildren(militaryPath, child.getId(), idList);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 09:50:57 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 根据军标ID获取模型数据访问URL
|
|
|
|
|
|
*/
|
|
|
|
|
|
private String getMilitaryDataUrlByModelId(String militaryId) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 获取当前启用的军标库路径
|
|
|
|
|
|
String militaryLibraryPath = getMilitaryLibrary();
|
|
|
|
|
|
if (militaryLibraryPath == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 查询军标对应的类型后缀
|
|
|
|
|
|
String sql = "SELECT military_type FROM military WHERE id = ?";
|
|
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(militaryId);
|
|
|
|
|
|
Military military = SQLiteUtil.queryForObject(militaryLibraryPath, sql, params, Military.class);
|
|
|
|
|
|
// 得到类型ID
|
|
|
|
|
|
String militaryType = military.getMilitaryType();
|
|
|
|
|
|
// 拼接完整URL
|
|
|
|
|
|
return "http://" + serverHost + ":" + serverPort + "/militaryLibrary/data/military/" + militaryId + "/" + militaryType;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-29 17:34:21 +08:00
|
|
|
|
private boolean isMilitaryTypeExist(String militaryPath, String typeId)
|
|
|
|
|
|
throws SQLException, IllegalAccessException, InstantiationException {
|
|
|
|
|
|
String checkSql = "SELECT id FROM military_type WHERE id = ?";
|
|
|
|
|
|
List<Object> params = new ArrayList<>();
|
|
|
|
|
|
params.add(typeId);
|
|
|
|
|
|
List<MilitaryType> existList = SQLiteUtil.queryForList(
|
|
|
|
|
|
militaryPath, checkSql, params, MilitaryType.class
|
|
|
|
|
|
);
|
|
|
|
|
|
return existList != null && !existList.isEmpty();
|
|
|
|
|
|
}
|
2025-09-26 13:46:54 +08:00
|
|
|
|
}
|