398 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			398 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| 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;
 | ||
| import com.yj.earth.business.domain.IconLibrary;
 | ||
| import com.yj.earth.business.domain.IconType;
 | ||
| import com.yj.earth.business.service.FileInfoService;
 | ||
| import com.yj.earth.business.service.IconLibraryService;
 | ||
| import com.yj.earth.common.util.ApiResponse;
 | ||
| import com.yj.earth.common.util.SQLiteUtil;
 | ||
| import com.yj.earth.dto.iconLibrary.AddIconTypeDto;
 | ||
| import com.yj.earth.dto.iconLibrary.CreateIconLibraryDto;
 | ||
| import com.yj.earth.dto.iconLibrary.DragIconTypeDto;
 | ||
| import com.yj.earth.dto.iconLibrary.UpdateIconTypeNameDto;
 | ||
| import com.yj.earth.vo.IconTypeVo;
 | ||
| import com.yj.earth.vo.IconVo;
 | ||
| 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.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;
 | ||
| import java.sql.SQLException;
 | ||
| import java.time.LocalDateTime;
 | ||
| import java.util.ArrayList;
 | ||
| import java.util.List;
 | ||
| import java.util.Map;
 | ||
| import java.util.stream.Collectors;
 | ||
| 
 | ||
| @Tag(name = "图标库管理")
 | ||
| @CheckAuth
 | ||
| @RestController
 | ||
| @RequestMapping("/iconLibrary")
 | ||
| public class IconLibraryController {
 | ||
|     @Resource
 | ||
|     private IconLibraryService iconLibraryService;
 | ||
|     @Resource
 | ||
|     private FileInfoService fileInfoService;
 | ||
| 
 | ||
|     @Operation(summary = "创建图标库")
 | ||
|     @PostMapping("/createIconLibrary")
 | ||
|     public ApiResponse createIconLibrary(@RequestBody CreateIconLibraryDto createIconLibraryDto) {
 | ||
|         try {
 | ||
|             // 参数校验与路径处理
 | ||
|             String folderPath = createIconLibraryDto.getPath();
 | ||
|             String iconName = createIconLibraryDto.getName();
 | ||
|             File parentDir = new File(folderPath);
 | ||
|             File iconFile = new File(parentDir, iconName);
 | ||
|             String iconPath = iconFile.getAbsolutePath().replace("\\", "/");
 | ||
| 
 | ||
|             // 检查父目录(不存在则创建)
 | ||
|             if (!parentDir.exists()) {
 | ||
|                 boolean mkdirsSuccess = parentDir.mkdirs();
 | ||
|                 if (!mkdirsSuccess) {
 | ||
|                     return ApiResponse.failure("创建图标库父目录失败:" + folderPath);
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             // 检查图标库文件是否已存在
 | ||
|             if (iconFile.exists()) {
 | ||
|                 if (iconFile.isDirectory()) {
 | ||
|                     return ApiResponse.failure("同名目录已存在、无法创建图标库文件:" + iconPath);
 | ||
|                 }
 | ||
|                 return ApiResponse.failure("图标库文件已存在:" + iconPath);
 | ||
|             }
 | ||
| 
 | ||
|             // 创建图标库文件
 | ||
|             boolean createSuccess = iconFile.createNewFile();
 | ||
|             if (!createSuccess) {
 | ||
|                 return ApiResponse.failure("创建图标库文件失败:" + iconPath);
 | ||
|             }
 | ||
| 
 | ||
|             // 新增图标库记录并初始化SQLite表结构
 | ||
|             addIconLibrary(iconPath);
 | ||
|             SQLiteUtil.initializationIcon(iconPath);
 | ||
|             return ApiResponse.success(null);
 | ||
|         } catch (Exception e) {
 | ||
|             return ApiResponse.failure("创建图标库失败:" + e.getMessage());
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "导入图标库")
 | ||
|     @PostMapping("/importIconLibrary")
 | ||
|     public ApiResponse importIconLibrary(@RequestParam("iconPath") @Parameter(description = "图标库路径") String iconPath) {
 | ||
|         addIconLibrary(iconPath);
 | ||
|         return ApiResponse.success(null);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "添加图标类型")
 | ||
|     @PostMapping("/addIconType")
 | ||
|     public ApiResponse addIconType(@RequestBody AddIconTypeDto addIconTypeDto) throws SQLException, IllegalAccessException, InstantiationException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == null) {
 | ||
|             return ApiResponse.failure("请先创建或导入图标库");
 | ||
|         }
 | ||
| 
 | ||
|         // 检查父级图标类型是否存在
 | ||
|         String parentId = addIconTypeDto.getParentId();
 | ||
|         if (parentId != null) {
 | ||
|             String sql = "SELECT * FROM icon_type WHERE id = ?";
 | ||
|             List<Object> params = new ArrayList<>();
 | ||
|             params.add(parentId);
 | ||
|             IconType iconType = SQLiteUtil.queryForObject(iconPath, sql, params, IconType.class);
 | ||
|             if (iconType == null) {
 | ||
|                 return ApiResponse.failure("父级图标类型不存在");
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         // 插入图标类型
 | ||
|         String sql = "INSERT INTO icon_type " +
 | ||
|                 "(id, name, parent_id, tree_index, created_at) " +
 | ||
|                 "VALUES (?, ?, ?, ?, ?)";
 | ||
|         List<Object> params = new ArrayList<>();
 | ||
|         params.add(UUID.fastUUID().toString(true));
 | ||
|         params.add(addIconTypeDto.getName());
 | ||
|         params.add(addIconTypeDto.getParentId());
 | ||
|         params.add(0);
 | ||
|         params.add(LocalDateTime.now());
 | ||
|         SQLiteUtil.executeUpdate(iconPath, sql, params);
 | ||
|         return ApiResponse.success(null);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "删除图标类型")
 | ||
|     @PostMapping("/deleteIconType")
 | ||
|     public ApiResponse deleteIconType(@Parameter(description = "图标类型ID") @RequestParam("iconTypeId") String iconTypeId) throws SQLException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == null) {
 | ||
|             return ApiResponse.failure("请先创建或导入图标库");
 | ||
|         }
 | ||
| 
 | ||
|         // 删除图标类型
 | ||
|         String sql = "DELETE FROM icon_type WHERE id = ?";
 | ||
|         List<Object> params = new ArrayList<>();
 | ||
|         params.add(iconTypeId);
 | ||
|         SQLiteUtil.executeUpdate(iconPath, sql, params);
 | ||
|         return ApiResponse.success(null);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "修改图标类型名称")
 | ||
|     @PostMapping("/updateIconTypeName")
 | ||
|     public ApiResponse updateIconTypeName(@RequestBody UpdateIconTypeNameDto updateIconTypeNameDto) throws SQLException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == null) {
 | ||
|             return ApiResponse.failure("请先创建或导入图标库");
 | ||
|         }
 | ||
| 
 | ||
|         // 更新图标类型名称
 | ||
|         String sql = "UPDATE icon_type SET name = ? WHERE id = ?";
 | ||
|         List<Object> params = new ArrayList<>();
 | ||
|         params.add(updateIconTypeNameDto.getName());
 | ||
|         params.add(updateIconTypeNameDto.getId());
 | ||
|         SQLiteUtil.executeUpdate(iconPath, sql, params);
 | ||
|         return ApiResponse.success(null);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "图标类型列表")
 | ||
|     @GetMapping("/iconTypeTree")
 | ||
|     public ApiResponse iconTypeTree() throws SQLException, IllegalAccessException, InstantiationException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == 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 icon_type ORDER BY tree_index ASC
 | ||
|                 """;
 | ||
|         List<IconType> iconTypes = SQLiteUtil.queryForList(iconPath, sql, null, IconType.class);
 | ||
| 
 | ||
|         // 构建树形结构
 | ||
|         List<IconTypeVo> treeList = buildIconTypeTree(iconTypes);
 | ||
|         return ApiResponse.success(treeList);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "拖动图标类型树")
 | ||
|     @PostMapping("/dragIconType")
 | ||
|     public ApiResponse dragIconType(@RequestBody DragIconTypeDto dragIconTypeDto) throws SQLException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == null) {
 | ||
|             return ApiResponse.failure("请先创建或导入图标库");
 | ||
|         }
 | ||
| 
 | ||
|         // 动态构建更新SQL
 | ||
|         List<String> updateFields = new ArrayList<>();
 | ||
|         List<Object> params = new ArrayList<>();
 | ||
| 
 | ||
|         if (dragIconTypeDto.getParentId() != null) {
 | ||
|             updateFields.add("parent_id = ?");
 | ||
|             params.add(dragIconTypeDto.getParentId());
 | ||
|         }
 | ||
|         if (dragIconTypeDto.getTreeIndex() != null) {
 | ||
|             updateFields.add("tree_index = ?");
 | ||
|             params.add(dragIconTypeDto.getTreeIndex());
 | ||
|         }
 | ||
| 
 | ||
|         String sql = "UPDATE icon_type SET " + String.join(", ", updateFields) + " WHERE id = ?";
 | ||
|         params.add(dragIconTypeDto.getId());
 | ||
|         SQLiteUtil.executeUpdate(iconPath, sql, params);
 | ||
|         return ApiResponse.success(null);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "添加图标文件")
 | ||
|     @PostMapping("/addIconFile")
 | ||
|     public ApiResponse addIconFile(@RequestParam("files") MultipartFile[] files,
 | ||
|                                    @Parameter(description = "图标类型ID") @RequestParam("iconTypeId") String iconTypeId)
 | ||
|             throws IOException, SQLException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == null) {
 | ||
|             return ApiResponse.failure("请先创建或导入图标库");
 | ||
|         }
 | ||
| 
 | ||
|         // 循环处理上传文件
 | ||
|         for (MultipartFile file : files) {
 | ||
|             if (file.isEmpty()) continue;
 | ||
| 
 | ||
|             String fileName = file.getOriginalFilename();
 | ||
|             if (fileName == null) continue;
 | ||
| 
 | ||
|             String fileSuffix = FileUtil.extName(fileName);
 | ||
|             String fileNameWithoutSuffix = FileUtil.mainName(fileName);
 | ||
| 
 | ||
|             // 上传文件并获取访问URL
 | ||
|             String url = fileInfoService.uploadWithPreview(file);
 | ||
| 
 | ||
|             // 插入图标记录
 | ||
|             String sql = "INSERT INTO icon " +
 | ||
|                     "(id, icon_type_id, icon_name, icon_type, data, created_at) " +
 | ||
|                     "VALUES (?, ?, ?, ?, ?, ?)";
 | ||
|             List<Object> params = new ArrayList<>();
 | ||
|             params.add(UUID.fastUUID().toString(true));
 | ||
|             params.add(iconTypeId);
 | ||
|             params.add(fileNameWithoutSuffix);
 | ||
|             params.add(fileSuffix);
 | ||
|             params.add(url);
 | ||
|             params.add(LocalDateTime.now());
 | ||
| 
 | ||
|             SQLiteUtil.executeUpdate(iconPath, sql, params);
 | ||
|         }
 | ||
| 
 | ||
|         return ApiResponse.success(null);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "根据图标类型查看图标列表")
 | ||
|     @PostMapping("/iconList")
 | ||
|     public ApiResponse iconList(@Parameter(description = "图标类型ID") @RequestParam("iconTypeId") String iconTypeId)
 | ||
|             throws SQLException, IllegalAccessException, InstantiationException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == null) {
 | ||
|             return ApiResponse.failure("请先创建或导入图标库");
 | ||
|         }
 | ||
| 
 | ||
|         // 多表联查图标数据
 | ||
|         String sql = """
 | ||
|                 SELECT
 | ||
|                     icon.id,
 | ||
|                     icon.icon_type_id as iconTypeId,
 | ||
|                     icon.icon_name as iconName,
 | ||
|                     icon.icon_type as iconType,
 | ||
|                     icon.data,
 | ||
|                     
 | ||
|                     icon.view,
 | ||
|                     icon.created_at as createdAt,
 | ||
|                     icon.updated_at as updatedAt,
 | ||
|                     icon_type.name as iconTypeName 
 | ||
|                 FROM icon 
 | ||
|                 JOIN icon_type ON icon.icon_type_id = icon_type.id
 | ||
|                 WHERE icon.icon_type_id = ?
 | ||
|                 """;
 | ||
|         List<Object> params = new ArrayList<>();
 | ||
|         params.add(iconTypeId);
 | ||
|         List<IconVo> iconVos = SQLiteUtil.queryForList(iconPath, sql, params, IconVo.class);
 | ||
|         return ApiResponse.success(iconVos);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "更新图标信息")
 | ||
|     @PostMapping("/updateIconInfo")
 | ||
|     public ApiResponse updateIconInfo(@Parameter(description = "图标ID") @RequestParam("iconId") String iconId,
 | ||
|                                       @Parameter(description = "图标名称") @RequestParam(value = "iconName", required = false) String iconName)
 | ||
|             throws SQLException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == null) {
 | ||
|             return ApiResponse.failure("请先创建或导入图标库");
 | ||
|         }
 | ||
| 
 | ||
|         // 无更新字段直接返回成功
 | ||
|         if (!StringUtils.hasText(iconName)) {
 | ||
|             return ApiResponse.success(null);
 | ||
|         }
 | ||
| 
 | ||
|         // 更新图标名称
 | ||
|         String sql = "UPDATE icon SET updated_at = ?, icon_name = ? WHERE id = ?";
 | ||
|         List<Object> params = new ArrayList<>();
 | ||
|         params.add(LocalDateTime.now());
 | ||
|         params.add(iconName);
 | ||
|         params.add(iconId);
 | ||
|         SQLiteUtil.executeUpdate(iconPath, sql, params);
 | ||
|         return ApiResponse.success(null);
 | ||
|     }
 | ||
| 
 | ||
|     @Operation(summary = "删除图标")
 | ||
|     @PostMapping("/deleteIcon")
 | ||
|     public ApiResponse deleteIcon(@Parameter(description = "图标ID") @RequestParam("iconId") String iconId) throws SQLException {
 | ||
|         String iconPath = getIconLibrary();
 | ||
|         if (iconPath == null) {
 | ||
|             return ApiResponse.failure("请先创建或导入图标库");
 | ||
|         }
 | ||
| 
 | ||
|         // 删除图标
 | ||
|         String sql = "DELETE FROM icon WHERE id = ?";
 | ||
|         List<Object> params = new ArrayList<>();
 | ||
|         params.add(iconId);
 | ||
|         SQLiteUtil.executeUpdate(iconPath, sql, params);
 | ||
|         return ApiResponse.success(null);
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 构建图标类型树形结构
 | ||
|      *
 | ||
|      * @param iconTypes 图标类型列表
 | ||
|      * @return 树形结构列表
 | ||
|      */
 | ||
|     private List<IconTypeVo> buildIconTypeTree(List<IconType> iconTypes) {
 | ||
|         // 转换为VO列表
 | ||
|         List<IconTypeVo> treeNodes = iconTypes.stream()
 | ||
|                 .map(IconTypeVo::new)
 | ||
|                 .collect(Collectors.toList());
 | ||
| 
 | ||
|         // 构建ID到VO的映射(便于快速查找父节点)
 | ||
|         Map<String, IconTypeVo> nodeMap = treeNodes.stream()
 | ||
|                 .collect(Collectors.toMap(IconTypeVo::getId, node -> node));
 | ||
| 
 | ||
|         // 组装树形结构
 | ||
|         List<IconTypeVo> rootNodes = new ArrayList<>();
 | ||
|         for (IconTypeVo node : treeNodes) {
 | ||
|             String parentId = node.getParentId();
 | ||
|             if (parentId == null || parentId.isEmpty()) {
 | ||
|                 // 无父节点 → 根节点
 | ||
|                 rootNodes.add(node);
 | ||
|             } else {
 | ||
|                 // 有父节点 → 加入父节点的子列表
 | ||
|                 IconTypeVo parentNode = nodeMap.get(parentId);
 | ||
|                 if (parentNode != null) {
 | ||
|                     parentNode.getChildren().add(node);
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         return rootNodes;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * 获取当前启用的图标库路径
 | ||
|      *
 | ||
|      * @return 图标库路径(null表示无启用的图标库)
 | ||
|      */
 | ||
|     private String getIconLibrary() {
 | ||
|         LambdaQueryWrapper<IconLibrary> queryWrapper = new LambdaQueryWrapper<>();
 | ||
|         queryWrapper.eq(IconLibrary::getIsEnable, 1);
 | ||
|         IconLibrary iconLibrary = iconLibraryService.getOne(queryWrapper);
 | ||
|         return iconLibrary == null ? null : iconLibrary.getPath();
 | ||
|     }
 | ||
| 
 | ||
|     private void addIconLibrary(String iconPath) {
 | ||
|         // 查询所有图标库并置为禁用
 | ||
|         List<IconLibrary> iconLibraries = iconLibraryService.list();
 | ||
|         for (IconLibrary iconLibrary : iconLibraries) {
 | ||
|             iconLibrary.setIsEnable(0);
 | ||
|             iconLibraryService.updateById(iconLibrary);
 | ||
|         }
 | ||
| 
 | ||
|         // 检查路径是否已存在(存在则启用、不存在则新增)
 | ||
|         LambdaQueryWrapper<IconLibrary> pathWrapper = new LambdaQueryWrapper<>();
 | ||
|         pathWrapper.eq(IconLibrary::getPath, iconPath);
 | ||
|         IconLibrary existingIconLib = iconLibraryService.getOne(pathWrapper);
 | ||
| 
 | ||
|         if (existingIconLib != null) {
 | ||
|             existingIconLib.setIsEnable(1);
 | ||
|             iconLibraryService.updateById(existingIconLib);
 | ||
|         } else {
 | ||
|             // 新增图标库记录
 | ||
|             IconLibrary newIconLib = new IconLibrary();
 | ||
|             File iconFile = FileUtil.file(iconPath);
 | ||
|             newIconLib.setId(UUID.fastUUID().toString(true));
 | ||
|             newIconLib.setPath(iconPath);
 | ||
|             newIconLib.setName(FileUtil.extName(iconFile));
 | ||
|             newIconLib.setIsEnable(1);
 | ||
|             iconLibraryService.save(newIconLib);
 | ||
|         }
 | ||
|     }
 | ||
| }
 | 
