Files
yjearth/src/main/java/com/yj/earth/business/controller/IconLibraryController.java

398 lines
16 KiB
Java
Raw Normal View History

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;
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,
2025-09-29 13:56:36 +08:00
2025-09-26 13:46:54 +08:00
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);
}
}
}