Quellcode durchsuchen

资料库后端

lipenghui vor 2 Wochen
Ursprung
Commit
96717f17dd

+ 140 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/FileUploadController.java

@@ -0,0 +1,140 @@
+package cn.iocoder.yudao.module.pms.controller.admin;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.exception.ErrorCode;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.security.PermitAll;
+import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+
+@RestController
+@RequestMapping("/rq/file")
+@Slf4j
+public class FileUploadController {
+
+    @Value("${file.upload-path}")
+    private String uploadPath;
+
+    @PostMapping("/upload")
+    @PermitAll
+    @TenantIgnore
+    public CommonResult<Map<String, Object>> uploadFiles(
+            @RequestParam("files") MultipartFile[] files,
+            @RequestParam(value = "isFolder", defaultValue = "false") boolean isFolder,
+            HttpServletRequest request) {
+
+        // 创建根目录(如果不存在)
+        File rootDir = new File(uploadPath);
+        if (!rootDir.exists()) {
+            rootDir.mkdirs();
+        }
+
+        List<Map<String, Object>> fileList = new ArrayList<>();
+        Map<String, Object> folderStructure = new HashMap<>();
+
+        try {
+            for (MultipartFile file : files) {
+                if (file.isEmpty()) {
+                    continue;
+                }
+
+                // 获取原始文件名(包含路径信息)
+                String originalFilename = file.getOriginalFilename();
+                if (StrUtil.isBlank(originalFilename)) {
+                    continue;
+                }
+
+                // 构建文件保存路径
+                Path filePath = Paths.get(uploadPath, originalFilename);
+
+                // 创建父目录
+                File parentDir = filePath.getParent().toFile();
+                if (!parentDir.exists()) {
+                    parentDir.mkdirs();
+                }
+
+                // 保存文件
+                file.transferTo(filePath.toFile());
+
+                // 记录文件信息
+                Map<String, Object> fileInfo = new HashMap<>();
+                fileInfo.put("name", FileUtil.getName(originalFilename));
+                fileInfo.put("path", originalFilename);
+                fileInfo.put("size", file.getSize());
+                fileInfo.put("isFolder", false);
+                fileList.add(fileInfo);
+
+                // 构建文件夹结构
+                buildFolderStructure(folderStructure, originalFilename);
+            }
+
+            Map<String, Object> result = new HashMap<>();
+            result.put("files", fileList);
+            result.put("folderStructure", folderStructure);
+            result.put("message", "上传成功");
+
+            System.out.println("------------------"+ JSON.toJSONString(result));
+            return CommonResult.success(result);
+
+        } catch (IOException e) {
+            log.error("文件上传失败", e);
+            return CommonResult.error(new ErrorCode(122, e.getMessage()));
+        }
+    }
+
+    /**
+     * 构建文件夹层级结构
+     */
+    private void buildFolderStructure(Map<String, Object> structure, String filePath) {
+        String[] pathParts = filePath.split("/");
+
+        // 如果是文件,最后一部分是文件名
+        boolean isFile = pathParts.length > 0 && FileUtil.isFile(filePath);
+        int depth = isFile ? pathParts.length - 1 : pathParts.length;
+
+//        Map<String, Object> currentLevel = structure;
+
+        for (int i = 0; i < depth; i++) {
+            String part = pathParts[i];
+            boolean isLastFolder = i == depth - 1;
+
+            if (!structure.containsKey(part)) {
+                Map<String, Object> newLevel = new HashMap<>();
+                newLevel.put("isFolder", true);
+                newLevel.put("children", new HashMap<>());
+
+                if (isLastFolder && isFile) {
+                    // 如果是文件的父文件夹,添加文件信息
+                    List<String> files = (List<String>) newLevel.getOrDefault("files", new ArrayList<>());
+                    files.add(pathParts[pathParts.length - 1]);
+                    newLevel.put("files", files);
+                }
+
+                structure.put(part, newLevel);
+            } else {
+                // 如果文件夹已存在,检查是否需要添加文件
+                if (isLastFolder && isFile) {
+                    Map<String, Object> existingLevel = (Map<String, Object>) structure.get(part);
+                    List<String> files = (List<String>) existingLevel.getOrDefault("files", new ArrayList<>());
+                    files.add(pathParts[pathParts.length - 1]);
+                    existingLevel.put("files", files);
+                }
+            }
+
+            // 进入下一级
+            structure = (Map<String, Object>) ((Map<String, Object>) structure.get(part)).get("children");
+        }
+    }
+}

+ 2 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/IotInfoController.java

@@ -147,4 +147,6 @@ public class IotInfoController {
                         BeanUtils.toBean(list, IotInfoRespVO.class));
     }
 
+
+
 }

+ 16 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/FileUploadVO.java

@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.module.pms.controller.admin.vo;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class FileUploadVO {
+
+    private List<Map<String, Object>> files;
+
+    private Map<String, Object> folderStructure;
+
+    private String message;
+}

+ 4 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotInfoSaveReqVO.java

@@ -46,4 +46,8 @@ public class IotInfoSaveReqVO {
     private List<Map<String, String>> fileList;
 
     private String type;
+
+    private List<FileUploadVO> folderTree;
+
+    private String folderJson;
 }

+ 221 - 33
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/IotInfoServiceImpl.java

@@ -14,16 +14,19 @@ import cn.iocoder.yudao.module.pms.dal.mysql.IotInfoMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotTreeMapper;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -37,6 +40,7 @@ import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_INFO_NOT_E
  */
 @Service
 @Validated
+@Slf4j
 public class IotInfoServiceImpl implements IotInfoService {
 
     @Resource
@@ -51,6 +55,8 @@ public class IotInfoServiceImpl implements IotInfoService {
     private DeptApi deptApi;
     @Autowired
     private IotTreeMapper iotTreeMapper;
+    @Value("${file.url}")
+    private String fileUrl;
 
     @Override
     public List<IotInfoRespVO> getChildContentFile(Long classId) {
@@ -100,40 +106,45 @@ public class IotInfoServiceImpl implements IotInfoService {
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void createIotInfo(IotInfoSaveReqVO createReqVO) {
         // 插入
-        if (CollUtil.isEmpty(createReqVO.getFileList())) {
-            throw exception(IOT_INFO_NOT_EXISTS);
-        }
+//        if (CollUtil.isEmpty(createReqVO.getFileList())) {
+//            throw exception(IOT_INFO_NOT_EXISTS);
+//        }
         Long classId = createReqVO.getClassId();
         IotDeviceDO iotDevice = iotDeviceService.getIotDevice(createReqVO.getDeviceId());
-        List<IotInfoDO> collect = createReqVO.getFileList().stream().map(e -> {
-            IotInfoDO iotInfo = BeanUtils.toBean(createReqVO, IotInfoDO.class);
-            iotInfo.setFilename(StringUtils.substringAfterLast(e.get("url"), "/"));
-            iotInfo.setFilePath(e.get("url"));
-            iotInfo.setDeptId(iotDevice.getDeptId());
-            long size = Long.parseLong(e.get("size"));
-            double mb = size / (1024.0 * 1024.0);
-            iotInfo.setFileSize(String.format("%.2f MB", mb));
-            iotInfo.setDeleted(false);
-            if ("book".equals(createReqVO.getType())) {
-                IotInfoClassifyDO classify = iotInfoClassifyService.getIotInfoClassify(classId);
-                //如果是设备的话
-                IotTreeListReqVO reqVO = new IotTreeListReqVO();
-                if (classify.getParentId()==0) {
-                    reqVO.setType("device").setOriginId(classify.getDeviceId());
-                } else {
-                    reqVO.setType("file").setOriginId(classId);
-                }
-                List<IotTreeDO> iotTreeList = iotTreeService.getIotTreeList(reqVO);
-                if (CollUtil.isNotEmpty(iotTreeList)) {
-                    iotInfo.setClassId(iotTreeList.get(0).getId());
-                }
-            }
-            return iotInfo;
-        }).collect(Collectors.toList());
+        Long deptId = iotDevice.getDeptId();
+
+        importFileTree(createReqVO.getFolderJson(), classId, deptId, iotDevice.getId());
 
-        iotInfoMapper.insert(collect);
+//        List<IotInfoDO> collect = createReqVO.getFileList().stream().map(e -> {
+//            IotInfoDO iotInfo = BeanUtils.toBean(createReqVO, IotInfoDO.class);
+//            iotInfo.setFilename(StringUtils.substringAfterLast(e.get("url"), "/"));
+//            iotInfo.setFilePath(e.get("url"));
+//            iotInfo.setDeptId(iotDevice.getDeptId());
+//            long size = Long.parseLong(e.get("size"));
+//            double mb = size / (1024.0 * 1024.0);
+//            iotInfo.setFileSize(String.format("%.2f MB", mb));
+//            iotInfo.setDeleted(false);
+//            if ("book".equals(createReqVO.getType())) {
+//                IotInfoClassifyDO classify = iotInfoClassifyService.getIotInfoClassify(classId);
+//                //如果是设备的话
+//                IotTreeListReqVO reqVO = new IotTreeListReqVO();
+//                if (classify.getParentId()==0) {
+//                    reqVO.setType("device").setOriginId(classify.getDeviceId());
+//                } else {
+//                    reqVO.setType("file").setOriginId(classId);
+//                }
+//                List<IotTreeDO> iotTreeList = iotTreeService.getIotTreeList(reqVO);
+//                if (CollUtil.isNotEmpty(iotTreeList)) {
+//                    iotInfo.setClassId(iotTreeList.get(0).getId());
+//                }
+//            }
+//            return iotInfo;
+//        }).collect(Collectors.toList());
+
+//        iotInfoMapper.insert(collect);
     }
     @Override
     public void updateIotInfo(IotInfoSaveReqVO updateReqVO) {
@@ -228,4 +239,181 @@ public class IotInfoServiceImpl implements IotInfoService {
     }
 
 
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+
+
+    public void importFileTree(String jsonData, Long parentId, Long deptId, Long deviceId) {
+        try {
+            // 解析JSON数组
+            JsonNode rootNode = objectMapper.readTree(jsonData);
+
+            if (rootNode.isArray()) {
+                for (JsonNode itemNode : rootNode) {
+                    // 处理文件夹结构
+                    JsonNode folderStructureNode = itemNode.get("folderStructure");
+                    Long fileClassId = null;
+                    if (folderStructureNode != null) {
+                        fileClassId = processFolderStructure(folderStructureNode, parentId, deptId);
+                    }
+
+                    // todo 处理文件
+                    JsonNode filesNode = itemNode.get("files");
+                    if (filesNode != null && filesNode.isArray()&&Objects.nonNull(fileClassId)) {
+                        processFiles(filesNode, parentId, fileClassId, deviceId, deptId);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("导入文件树结构失败", e);
+            throw new RuntimeException("导入文件树结构失败", e);
+        }
+    }
+
+    /**
+     * 处理文件夹结构
+     */
+//    private void processFolderStructure(JsonNode folderStructureNode, Long parentId, Long deptId) {
+//        Iterator<String> fieldNames = folderStructureNode.fieldNames();
+//
+//        while (fieldNames.hasNext()) {
+//            String folderName = fieldNames.next();
+//            JsonNode folderNode = folderStructureNode.get(folderName);
+//
+//            if (folderName.contains(".")) {
+//                break;
+//            }
+//            IotTreeDO iotTreeDO = iotTreeMapper.selectOne("name", folderName, "parent_id", parentId);
+//
+//
+//            Long currentNodeId;
+//            if (iotTreeDO != null) {
+//                currentNodeId = iotTreeDO.getId();
+//            } else {
+//                // 插入当前文件夹节点
+////                IotTreeDO folder = new IotTreeDO(folderName, parentId);
+////                save(folder);
+//                IotTreeDO folder = new IotTreeDO();
+//                folder.setParentId(parentId);
+//                folder.setName(folderName);
+//                folder.setDeleted(false);
+//                folder.setType("file");
+//                folder.setDeptId(deptId);
+//                iotTreeMapper.insert(folder);
+//                currentNodeId = folder.getId();
+//            }
+//
+//            // 递归处理子文件夹
+//            JsonNode childrenNode = folderNode.get("children");
+//            if (childrenNode != null && !childrenNode.isNull() && !childrenNode.isEmpty()) {
+//                processFolderStructure(childrenNode, currentNodeId, deptId);
+//            }
+//        }
+//    }
+
+    /**
+     * 处理文件夹结构并递归创建节点,当遇到包含"."的文件夹名时返回其parentId
+     * @param folderStructureNode 文件夹结构的JSON节点
+     * @param parentId 父节点ID
+     * @param deptId 部门ID
+     * @return 遇到包含"."的文件夹时返回其parentId,否则返回null
+     */
+    private Long processFolderStructure(JsonNode folderStructureNode, Long parentId, Long deptId) {
+        Iterator<String> fieldNames = folderStructureNode.fieldNames();
+
+        while (fieldNames.hasNext()) {
+            String folderName = fieldNames.next();
+            JsonNode folderNode = folderStructureNode.get(folderName);
+
+            // 检查文件夹名是否包含".",如果是则返回当前parentId
+            if (folderName.contains(".")) {
+                return parentId; // 返回当前节点的父ID
+            }
+
+            // 查询是否已存在同名同父节点的记录
+            IotTreeDO iotTreeDO = iotTreeMapper.selectOne("name", folderName, "parent_id", parentId);
+
+            Long currentNodeId;
+            if (iotTreeDO != null) {
+                currentNodeId = iotTreeDO.getId();
+            } else {
+                // 创建新节点
+                IotTreeDO folder = new IotTreeDO();
+                folder.setParentId(parentId);
+                folder.setName(folderName);
+                folder.setDeleted(false);
+                folder.setType("file");
+                folder.setDeptId(deptId);
+                iotTreeMapper.insert(folder);
+                currentNodeId = folder.getId();
+            }
+
+            // 递归处理子文件夹
+            JsonNode childrenNode = folderNode.get("children");
+            if (childrenNode != null && !childrenNode.isNull() && !childrenNode.isEmpty()) {
+                // 递归调用,如果子节点处理中返回了parentId,则向上传递
+                Long result = processFolderStructure(childrenNode, currentNodeId, deptId);
+                if (result != null) {
+                    return result; // 子节点处理中遇到了目标,返回结果
+                }
+            }
+        }
+
+        // 正常处理完所有节点,未遇到包含"."的文件夹
+        return null;
+    }
+
+    /**
+     * 处理文件
+     */
+    private void processFiles(JsonNode filesNode, Long rootParentId,Long fileClassId, Long deviceId, Long deptId) {
+        for (JsonNode fileNode : filesNode) {
+            String path = fileNode.get("path").asText();
+            String fileName = fileNode.get("name").asText();
+
+            // 根据路径确定父文件夹ID
+            String[] pathParts = path.split("/");
+            Long parentId = rootParentId;
+
+            // 逐级查找或创建父文件夹
+            for (int i = 0; i < pathParts.length - 1; i++) {
+                String folderName = pathParts[i];
+                parentId = findOrCreateFolder(folderName, parentId);
+            }
+
+            // 检查文件是否已存在
+            IotInfoDO iotInfoDO = iotInfoMapper.selectOne("filename", fileName, "class_id", fileClassId);
+            if (iotInfoDO == null) {
+                IotInfoDO info = new IotInfoDO();
+                info.setDeviceId(deviceId);
+                info.setDeptId(deptId);
+                info.setClassId(fileClassId);
+                info.setFilename(fileName);
+                info.setDeleted(false);
+                info.setFileType("file");
+                if (fileName.contains("jpg")||fileName.contains("jpeg")||fileName.contains("png")||fileName.contains("gif")) {
+                    info.setFileType("pic");
+                }
+                info.setFilePath(fileUrl+fileName);
+                iotInfoMapper.insert(info);
+            }
+        }
+    }
+
+    /**
+     * 查找或创建文件夹
+     */
+    private Long findOrCreateFolder(String folderName, Long parentId) {
+        IotTreeDO folder = iotTreeMapper.selectOne("name", folderName, "parent_id", parentId);
+
+        if (folder == null) {
+            folder.setParentId(parentId);
+            folder.setName(folderName);
+            folder.setDeleted(false);
+            folder.setType("file");
+            iotTreeMapper.insert(folder);
+        }
+
+        return folder.getId();
+    }
 }

+ 4 - 0
yudao-server/src/main/resources/application-dev.yaml

@@ -291,3 +291,7 @@ oa:
   oaSecret: kryfoa20250905@szh
   user: OAuser
   userid: 1234
+
+file:
+  upload-path: D:\wenjian
+  url: http://localhost:48080/admin-api/infra/file/29/get/