模型库、矢量文件

This commit is contained in:
ZZX9599
2025-09-29 17:34:21 +08:00
parent 94add25716
commit efe4ddf97b
11 changed files with 1159 additions and 719 deletions

View File

@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Tag(name = "业务配置管理")
@CheckAuth
@RestController

View File

@ -4,21 +4,27 @@ 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;
import com.yj.earth.business.domain.MilitaryLibrary;
import com.yj.earth.business.domain.MilitaryType;
import com.yj.earth.business.domain.MilitaryLibrary; // 需自定义对应军标库配置表同ModelLibrary结构
import com.yj.earth.business.domain.MilitaryType; // 需自定义对应military_type表实体
import com.yj.earth.business.service.FileInfoService;
import com.yj.earth.business.service.MilitaryLibraryService;
import com.yj.earth.business.service.MilitaryLibraryService; // 需自定义军标库Service同ModelLibraryService逻辑
import com.yj.earth.common.util.ApiResponse;
import com.yj.earth.common.util.FileCommonUtil;
import com.yj.earth.common.util.SQLiteUtil;
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;
import com.yj.earth.vo.MilitaryTypeVo;
import com.yj.earth.vo.MilitaryVo;
import com.yj.earth.dto.militaryLibrary.AddMilitaryTypeDto; // 需自定义添加军标类型DTO
import com.yj.earth.dto.militaryLibrary.CreateMilitaryLibraryDto; // 需自定义创建军标库DTO
import com.yj.earth.dto.militaryLibrary.DragMilitaryTypeDto; // 需自定义拖动军标类型DTO
import com.yj.earth.dto.militaryLibrary.UpdateMilitaryTypeNameDto; // 需自定义修改军标类型名称DTO
import com.yj.earth.vo.MilitaryDataVo;
import com.yj.earth.vo.MilitaryTypeVo; // 需自定义军标类型树形VO同ModelTypeVo结构
import com.yj.earth.vo.MilitaryVo; // 需自定义军标列表VO剔除海报相关字段
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@ -26,9 +32,12 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -38,44 +47,52 @@ import java.util.stream.Collectors;
@RestController
@RequestMapping("/militaryLibrary")
public class MilitaryLibraryController {
@Resource
private MilitaryLibraryService militaryLibraryService;
@Resource
private FileInfoService fileInfoService;
@Operation(summary = "创建军标库")
@PostMapping("/createMilitaryLibrary")
public ApiResponse createMilitaryLibrary(@RequestBody CreateMilitaryLibraryDto createMilitaryLibraryDto) {
public ApiResponse createMilitaryLibrary(@RequestBody CreateMilitaryLibraryDto createDto) {
try {
// 参数校验
String folderPath = createMilitaryLibraryDto.getPath();
String militaryName = createMilitaryLibraryDto.getName();
// 处理路径、组合为完整军标库文件路径
// 参数校验与路径处理
String folderPath = createDto.getPath();
String libraryName = createDto.getName();
if (!StringUtils.hasText(folderPath) || !StringUtils.hasText(libraryName)) {
return ApiResponse.failure("路径和名称不能为空");
}
// 构建完整军标库文件路径SQLite文件
File parentDir = new File(folderPath);
File militaryFile = new File(parentDir, militaryName);
File militaryFile = new File(parentDir, libraryName);
String militaryPath = militaryFile.getAbsolutePath().replace("\\", "/");
// 检查父目录是否存在、不存在则创建
// 父目录不存在则创建
if (!parentDir.exists()) {
boolean mkdirsSuccess = parentDir.mkdirs();
if (!mkdirsSuccess) {
return ApiResponse.failure("创建父目录失败:" + folderPath);
}
}
// 检查军标库文件是否已存在
// 校验军标库文件是否已存在
if (militaryFile.exists()) {
if (militaryFile.isDirectory()) {
return ApiResponse.failure("同名目录已存在无法创建文件:" + militaryPath);
return ApiResponse.failure("同名目录已存在无法创建文件:" + militaryPath);
}
return ApiResponse.failure("军标库文件已存在:" + militaryPath);
}
// 创建军标库文件
boolean createSuccess = militaryFile.createNewFile();
if (!createSuccess) {
// 创建SQLite文件
boolean createFileSuccess = militaryFile.createNewFile();
if (!createFileSuccess) {
return ApiResponse.failure("创建军标库文件失败:" + militaryPath);
}
// 添加军标库信息
addMilitaryLibrary(militaryPath);
// 初始化军标库表结构
SQLiteUtil.initializationMilitary(militaryPath);
// 添加军标库配置到数据库
addMilitaryLibrary(militaryPath);
return ApiResponse.success(null);
} catch (Exception e) {
return ApiResponse.failure("创建军标库失败:" + e.getMessage());
@ -84,304 +101,441 @@ public class MilitaryLibraryController {
@Operation(summary = "导入军标库")
@PostMapping("/importMilitaryLibrary")
public ApiResponse importMilitaryLibrary(@RequestParam("militaryPath") @Parameter(description = "军标库路径") String militaryPath) {
addMilitaryLibrary(militaryPath);
return ApiResponse.success(null);
public ApiResponse importMilitaryLibrary(
@RequestParam("militaryPath") @Parameter(description = "军标库SQLite文件路径") String militaryPath) {
try {
// 校验路径是否存在
File militaryFile = new File(militaryPath);
if (!militaryFile.exists() || !militaryFile.isFile()) {
return ApiResponse.failure("军标库文件不存在:" + militaryPath);
}
// 添加到配置表并启用
addMilitaryLibrary(militaryPath);
return ApiResponse.success(null);
} catch (Exception e) {
return ApiResponse.failure("导入军标库失败:" + e.getMessage());
}
}
@Operation(summary = "添加军标类型")
@PostMapping("/addMilitaryType")
public ApiResponse addMilitaryType(@RequestBody AddMilitaryTypeDto addMilitaryTypeDto) throws SQLException, IllegalAccessException, InstantiationException {
public ApiResponse addMilitaryType(@RequestBody AddMilitaryTypeDto addDto) throws SQLException, IllegalAccessException, InstantiationException {
// 获取当前启用的军标库路径
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 检查父级是否存在
String parentId = addMilitaryTypeDto.getParentId();
if (parentId != null) {
String sql = "SELECT * FROM military_type WHERE id = ?";
List<Object> params = new ArrayList<>();
params.add(parentId);
MilitaryType militaryType = SQLiteUtil.queryForObject(militaryPath, sql, params, MilitaryType.class);
if (militaryType == null) {
return ApiResponse.failure("父级军标类型不存在");
// 校验父级类型(若有)
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) {
return ApiResponse.failure("父级军标类型不存在:" + parentId);
}
}
String sql = "INSERT INTO military_type " +
// 插入军标类型
String insertSql = "INSERT INTO military_type " +
"(id, name, parent_id, tree_index, created_at) " +
"VALUES (?, ?, ?, ?, ?)";
List<Object> params = new ArrayList<>();
params.add(UUID.fastUUID().toString(true));
params.add(addMilitaryTypeDto.getName());
params.add(addMilitaryTypeDto.getParentId());
params.add(addDto.getName());
params.add(parentId);
params.add(0);
params.add(LocalDateTime.now());
SQLiteUtil.executeUpdate(militaryPath, sql, params);
return ApiResponse.success(null);
}
@Operation(summary = "删除军标类型")
@PostMapping("/deleteMilitaryType")
public ApiResponse deleteMilitaryType(@Parameter(description = "军标类型ID") @RequestParam("militaryTypeId") String militaryTypeId) throws SQLException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
String sql = "DELETE FROM military_type WHERE id = ?";
List<Object> params = new ArrayList<>();
params.add(militaryTypeId);
SQLiteUtil.executeUpdate(militaryPath, sql, params);
params.add(LocalDateTime.now().toString());
SQLiteUtil.executeUpdate(militaryPath, insertSql, params);
return ApiResponse.success(null);
}
@Operation(summary = "修改军标类型名称")
@PostMapping("/updateMilitaryTypeName")
public ApiResponse updateMilitaryTypeName(@RequestBody UpdateMilitaryTypeNameDto updateMilitaryTypeNameDto) throws SQLException {
public ApiResponse updateMilitaryTypeName(@RequestBody UpdateMilitaryTypeNameDto updateDto)
throws SQLException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
String sql = "UPDATE military_type SET name = ? WHERE id = ?";
// 执行更新
String updateSql = "UPDATE military_type SET name = ?, updated_at = ? WHERE id = ?";
List<Object> params = new ArrayList<>();
params.add(updateMilitaryTypeNameDto.getName());
params.add(updateMilitaryTypeNameDto.getId());
SQLiteUtil.executeUpdate(militaryPath, sql, params);
params.add(updateDto.getName());
params.add(LocalDateTime.now().toString());
params.add(updateDto.getId());
SQLiteUtil.executeUpdate(militaryPath, updateSql, params);
return ApiResponse.success(null);
}
@Operation(summary = "军标类型列表")
@GetMapping("/militaryTypeList")
@Operation(summary = "删除军标类型")
@PostMapping("/deleteMilitaryType")
public ApiResponse deleteMilitaryType(
@RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId)
throws SQLException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 执行删除
String deleteSql = "DELETE FROM military_type WHERE id = ?";
List<Object> params = new ArrayList<>();
params.add(typeId);
SQLiteUtil.executeUpdate(militaryPath, deleteSql, params);
return ApiResponse.success(null);
}
@Operation(summary = "军标类型树形列表")
@GetMapping("/militaryTypeTree")
public ApiResponse militaryTypeTree() throws SQLException, IllegalAccessException, InstantiationException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 查询所有军标类型
String sql = """
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> militaryTypes = SQLiteUtil.queryForList(militaryPath, sql, null, MilitaryType.class);
// 转换为树形结构
List<MilitaryTypeVo> treeList = buildMilitaryTypeTree(militaryTypes);
List<MilitaryTypeVo> treeList = militaryTypeList();
return ApiResponse.success(treeList);
}
@Operation(summary = "拖动军标类型树")
@PostMapping("/dragMilitaryType")
public ApiResponse dragMilitaryType(@RequestBody DragMilitaryTypeDto dragMilitaryTypeDto) throws SQLException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 动态构建SQL和参数
List<String> updateFields = new ArrayList<>();
List<Object> params = new ArrayList<>();
// 判断 parentId 是否存在
if (dragMilitaryTypeDto.getParentId() != null) {
updateFields.add("parent_id = ?");
params.add(dragMilitaryTypeDto.getParentId());
}
// 判断 treeIndex 是否存在
if (dragMilitaryTypeDto.getTreeIndex() != null) {
updateFields.add("tree_index = ?");
params.add(dragMilitaryTypeDto.getTreeIndex());
}
// 构建完整 SQL
String sql = "UPDATE military_type SET " + String.join(", ", updateFields) + " WHERE id = ?";
params.add(dragMilitaryTypeDto.getId());
SQLiteUtil.executeUpdate(militaryPath, sql, params);
return ApiResponse.success(null);
}
@Operation(summary = "添加军标文件")
@PostMapping("/addMilitaryFile")
public ApiResponse addMilitaryFile(@RequestParam("files") MultipartFile[] files, @Parameter(description = "军标类型ID") @RequestParam("militaryTypeId") String militaryTypeId) throws IOException, SQLException {
// 获取最新的军标库路径
public ApiResponse addMilitaryFile(@RequestParam("files") MultipartFile[] files, @RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId) throws IOException, SQLException, IllegalAccessException, InstantiationException {
// 获取当前启用的军标库
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 循环处理每个上传的文件
// 校验类型是否存在
if (!isMilitaryTypeExist(militaryPath, typeId)) {
return ApiResponse.failure("军标类型不存在:" + typeId);
}
// 循环处理每个文件
for (MultipartFile file : files) {
// 跳过空文件
if (file.isEmpty()) {
continue;
continue; // 跳过空文件
}
// 获取文件信息
String fileName = file.getOriginalFilename();
if (fileName == null) {
continue;
}
String fileSuffix = FileUtil.extName(fileName);
String fileNameWithoutSuffix = FileUtil.mainName(fileName);
// 构建插入SQL
String sql = "INSERT INTO military " +
"(id, military_type_id, military_name, military_type, data, created_at) " +
// 解析文件名与后缀
String originalFileName = file.getOriginalFilename();
if (originalFileName == null) {
continue;
}
String fileSuffix = FileUtil.extName(originalFileName);
String fileNameWithoutSuffix = FileUtil.mainName(originalFileName);
// 插入军标数据
String insertSql = "INSERT INTO military " +
"(id, military_type_id, military_name, military_type, military_data, created_at) " +
"VALUES (?, ?, ?, ?, ?, ?)";
String url = fileInfoService.uploadWithPreview(file);
List<Object> params = new ArrayList<>();
params.add(UUID.fastUUID().toString(true));
params.add(militaryTypeId);
params.add(typeId);
params.add(fileNameWithoutSuffix);
params.add(fileSuffix);
params.add(url);
params.add(LocalDateTime.now());
params.add(file.getBytes());
params.add(LocalDateTime.now().toString());
// 执行插入操作
SQLiteUtil.executeUpdate(militaryPath, sql, params);
SQLiteUtil.executeUpdate(militaryPath, insertSql, params);
}
return ApiResponse.success(null);
}
@Operation(summary = "根据军标类型查看军标列表")
@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 = "根据类型查询军标列表")
@PostMapping("/militaryList")
public ApiResponse militaryList(@Parameter(description = "军标类型ID") @RequestParam("militaryTypeId") String militaryTypeId) throws SQLException, IllegalAccessException, InstantiationException {
// 获取最新的军标库
public ApiResponse getMilitaryList(@RequestParam("militaryTypeId") @Parameter(description = "军标类型ID") String typeId) throws SQLException, IllegalAccessException, InstantiationException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 多表联查、查询所有的军标
String sql = """
SELECT
military.id,
military.military_type_id as militaryTypeId,
military.military_name as militaryName,
military.military_type as militaryType,
military.data,
military.view,
military.created_at as createdAt,
military.updated_at as updatedAt,
military_type.name as militaryTypeName from
military JOIN military_type ON military.military_type_id = military_type.id
WHERE military.military_type_id = ?
""";
List<Object> params = new ArrayList<>();
params.add(militaryTypeId);
List<MilitaryVo> militaryVos = SQLiteUtil.queryForList(militaryPath, sql, params, MilitaryVo.class);
return ApiResponse.success(militaryVos);
// 获取当前类型及所有子类型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);
}
@Operation(summary = "更新军标信息")
@PostMapping("/uploadMilitaryInfo")
public ApiResponse uploadMilitaryInfo(
@Parameter(description = "军标ID") @RequestParam("militaryId") String militaryId,
@Parameter(description = "军标名称") @RequestParam(value = "militaryName", required = false) String militaryName)
@Operation(summary = "更新军标名称")
@PostMapping("/updateMilitaryInfo")
public ApiResponse updateMilitaryInfo(
@RequestParam("militaryId") @Parameter(description = "军标ID") String militaryId,
@RequestParam("militaryName") @Parameter(description = "新军标名称") String militaryName)
throws SQLException {
// 获取最新的军标库路径
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 如果没有需要更新的字段、直接返回成功
if (!StringUtils.hasText(militaryName)) {
return ApiResponse.success(null);
}
// 构建更新SQL和参数
String sql = "UPDATE military SET updated_at = ?, military_name = ? WHERE id = ?";
String updateSql = "UPDATE military SET military_name = ?, updated_at = ? WHERE id = ?";
List<Object> params = new ArrayList<>();
params.add(LocalDateTime.now());
params.add(militaryName);
params.add(LocalDateTime.now().toString());
params.add(militaryId);
// 执行更新
SQLiteUtil.executeUpdate(militaryPath, sql, params);
SQLiteUtil.executeUpdate(militaryPath, updateSql, params);
return ApiResponse.success(null);
}
@Operation(summary = "删除军标")
@PostMapping("/deleteMilitary")
public ApiResponse deleteMilitary(@Parameter(description = "军标ID") @RequestParam("militaryId") String militaryId) throws SQLException {
public ApiResponse deleteMilitary(@RequestParam("militaryId") @Parameter(description = "军标ID") String militaryId) throws SQLException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
String sql = "DELETE FROM military WHERE id = ?";
// 执行删除
String deleteSql = "DELETE FROM military WHERE id = ?";
List<Object> params = new ArrayList<>();
params.add(militaryId);
SQLiteUtil.executeUpdate(militaryPath, sql, params);
return ApiResponse.success(null);
SQLiteUtil.executeUpdate(militaryPath, deleteSql, params);
return ApiResponse.success("删除军标成功");
}
private List<MilitaryTypeVo> buildMilitaryTypeTree(List<MilitaryType> militaryTypes) {
List<MilitaryTypeVo> treeNodes = militaryTypes.stream()
.map(militaryType -> new MilitaryTypeVo(militaryType))
.collect(Collectors.toList());
// 构建节点ID到节点的映射
Map<String, MilitaryTypeVo> nodeMap = treeNodes.stream()
.collect(Collectors.toMap(MilitaryTypeVo::getId, node -> node));
// 根节点列表
List<MilitaryTypeVo> rootNodes = new ArrayList<>();
// 为每个节点添加子节点
for (MilitaryTypeVo node : treeNodes) {
String parentId = node.getParentId();
@Operation(summary = "拖动调整军标类型层级")
@PostMapping("/dragMilitaryType")
public ApiResponse dragMilitaryType(@RequestBody List<DragMilitaryTypeDto> dragDtoList)
throws SQLException, IllegalAccessException, InstantiationException {
String militaryPath = getMilitaryLibrary();
if (militaryPath == null) {
return ApiResponse.failure("请先创建或导入军标库");
}
// 批量更新层级和排序
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);
}
private String getMilitaryLibrary() {
LambdaQueryWrapper<MilitaryLibrary> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MilitaryLibrary::getIsEnable, 1); // 1=启用0=未启用
MilitaryLibrary library = militaryLibraryService.getOne(queryWrapper);
return library == null ? null : library.getPath();
}
private void addMilitaryLibrary(String militaryPath) {
// 所有已存在的军标库设置为「未启用」
List<MilitaryLibrary> existLibraries = militaryLibraryService.list();
for (MilitaryLibrary library : existLibraries) {
library.setIsEnable(0);
militaryLibraryService.updateById(library);
}
// 检查路径是否已存在(存在则启用,不存在则新增)
LambdaQueryWrapper<MilitaryLibrary> pathWrapper = new LambdaQueryWrapper<>();
pathWrapper.eq(MilitaryLibrary::getPath, militaryPath);
MilitaryLibrary existLibrary = militaryLibraryService.getOne(pathWrapper);
if (existLibrary != null) {
existLibrary.setIsEnable(1);
militaryLibraryService.updateById(existLibrary);
} else {
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);
}
}
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()) {
// 没有父节点的是根节点
rootNodes.add(node);
rootList.add(vo);
} else {
// 找到父节点并添加为子节点
MilitaryTypeVo parentNode = nodeMap.get(parentId);
if (parentNode != null) {
parentNode.getChildren().add(node);
MilitaryTypeVo parentVo = voMap.get(parentId);
if (parentVo != null) {
parentVo.getChildren().add(vo);
}
}
}
return rootNodes;
// 排序
rootList.sort(Comparator.comparingInt(MilitaryTypeVo::getTreeIndex));
sortMilitaryTypeChildren(rootList);
return rootList;
}
private String getMilitaryLibrary() {
// 获取启用的军标库
LambdaQueryWrapper<MilitaryLibrary> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MilitaryLibrary::getIsEnable, 1);
MilitaryLibrary militaryLibrary = militaryLibraryService.getOne(queryWrapper);
if (militaryLibrary == null) {
return null;
}
return militaryLibrary.getPath();
}
private void addMilitaryLibrary(String militaryPath) {
// 查询系统所有的军标库
List<MilitaryLibrary> militaryLibraries = militaryLibraryService.list();
// 遍历并更新状态
for (MilitaryLibrary militaryLibrary : militaryLibraries) {
// 设置启用状态为0
militaryLibrary.setIsEnable(0);
militaryLibraryService.updateById(militaryLibrary);
}
// 检查相同路径的军标库是否已存在
LambdaQueryWrapper<MilitaryLibrary> pathWrapper = new LambdaQueryWrapper<>();
pathWrapper.eq(MilitaryLibrary::getPath, militaryPath);
MilitaryLibrary existingMilitary = militaryLibraryService.getOne(pathWrapper);
// 若存在相同路径的军标库、不做处理、仅仅更新状态为显示
if (existingMilitary != null) {
existingMilitary.setIsEnable(1);
militaryLibraryService.updateById(existingMilitary);
private void sortMilitaryTypeChildren(List<MilitaryTypeVo> voList) {
if (voList == null || voList.isEmpty()) {
return;
} else {
// 新增军标库
MilitaryLibrary newMilitary = new MilitaryLibrary();
File file = FileUtil.file(militaryPath);
newMilitary.setId(UUID.fastUUID().toString(true));
newMilitary.setPath(militaryPath);
newMilitary.setName(FileUtil.extName(file));
newMilitary.setIsEnable(1);
militaryLibraryService.save(newMilitary);
}
// 排序当前层级
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);
}
}
}
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();
}
}

View File

@ -313,12 +313,17 @@ public class ModelLibraryController {
// 循环遍历数据
for (ModelVo modelVo : modelVos) {
if (modelVo.getModelType() != null) {
modelVo.setModelDataUrl("/modelLibrary/data/model/" + modelVo.getId() + "/" + modelVo.getModelType());
String processedModelType = trimDot(modelVo.getModelType());
modelVo.setModelDataUrl("/modelLibrary/data/model/" + modelVo.getId() + "/" + processedModelType);
modelVo.setModelType(processedModelType);
}
if (modelVo.getPosterType() != null) {
modelVo.setPosterDataUrl("/modelLibrary/data/poster/" + modelVo.getId() + "/" + modelVo.getPosterType());
String processedPosterType = trimDot(modelVo.getPosterType());
modelVo.setPosterDataUrl("/modelLibrary/data/poster/" + modelVo.getId() + "/" + processedPosterType);
modelVo.setPosterType(processedPosterType);
}
}
return ApiResponse.success(modelVos);
}
@ -566,4 +571,12 @@ public class ModelLibraryController {
// 若查询结果非空、说明分类存在
return existTypes != null && !existTypes.isEmpty();
}
private String trimDot(String str) {
if (str == null) {
return null;
}
return str.startsWith(".") ? str.substring(1) : str;
}
}