blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/contants/ParamContants.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,13 @@ package org.springblade.mdm.commons.contants; public class ParamContants { public static final String NETWORK_TYPE_KEY = "networkType"; /** * æ¶å¯ç½ */ public static final String NETWORK_TYPE_SHEMI = "0"; /** * å·¥æ§ç½ */ public static final String NETWORK_TYPE_GONGKONG = "1"; } blade-service/blade-mdm/src/main/java/org/springblade/mdm/config/InitBean.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,89 @@ package org.springblade.mdm.config; import jakarta.annotation.PostConstruct; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springblade.core.tool.api.R; import org.springblade.mdm.basesetting.machine.MachineService; import org.springblade.mdm.basesetting.machine.entity.Machine; import org.springblade.mdm.commons.contants.ParamContants; import org.springblade.mdm.machineback.filewatch.DirectorLockService; import org.springblade.mdm.machineback.filewatch.DynamicDirectoryWatcher; import org.springblade.mdm.machineback.filewatch.FileWatcherService; import org.springblade.mdm.machineback.filewatch.MachineFileBackListener; import org.springblade.mdm.machineback.service.MachineBackFileService; import org.springblade.mdm.program.service.NcProgramService; import org.springblade.system.feign.ISysClient; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @Slf4j @AllArgsConstructor @Component public class InitBean { private final DirectorLockService directorLockService; private final MachineService machineService; private final FileWatcherService fileWatcherService; private final ISysClient sysClient; private final DynamicDirectoryWatcher directoryWatcher; private final MachineBackFileService machineBackFileService; private final NcProgramService ncProgramService; //private final FileWatcherService.FileChangeListener listener; @PostConstruct public void init() { System.out.println("åºç¨å¯å¨æ¶æ§è¡åå§åæä½ @PostConstruct"); // åå§åé»è¾ R<String> networkTypeR = sysClient.getParamValue(ParamContants.NETWORK_TYPE_KEY); String networkType = networkTypeR.getData() == null ? ParamContants.NETWORK_TYPE_SHEMI : networkTypeR.getData(); if (networkType.equals(ParamContants.NETWORK_TYPE_GONGKONG)) { initMachineDirMonitor(); } } /** * åå§åçæ§ç®å½ */ void initMachineDirMonitor() { boolean locked = directorLockService.acquireLock(); if (!locked) { log.info("åä¼ æ¥æ¶ç®å½å·²ç»è¢«å ¶ä»é¨ç½²ç¹ä½éå®ï¼ç´æ¥è¿å"); return; } List<Machine> machineList = machineService.list(); List<String> monitorDirList = new ArrayList<String>(); machineList.forEach(m -> { if (StringUtils.isNotEmpty(m.getProgReceiveDir())) { String dir = StringUtils.removeEnd(StringUtils.removeEnd(m.getProgReceiveDir(), "/"), "\\"); if (!monitorDirList.contains(dir)) { monitorDirList.add(dir); } } }); for (String dir : monitorDirList) { Path dirPath = Paths.get(dir); try { if(!dirPath.toFile().exists()) { dirPath.toFile().mkdirs(); } directoryWatcher.addDirectory(dirPath,getListener()); } catch (Exception e) { log.error("æ·»å çæ§ç®å½å¼å¸¸",e); } } } FileWatcherService.FileChangeListener getListener() { return new MachineFileBackListener(machineBackFileService,ncProgramService); } } blade-service/blade-mdm/src/main/java/org/springblade/mdm/config/ShutdownHook.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,21 @@ package org.springblade.mdm.config; import jakarta.annotation.PreDestroy; import lombok.AllArgsConstructor; import org.springblade.mdm.machineback.filewatch.DirectorLockService; import org.springframework.stereotype.Component; @AllArgsConstructor @Component public class ShutdownHook { private final DirectorLockService directorLockService; @PreDestroy public void onExit() { System.out.println("æ§è¡éåºåæ¸ çæä½..."); // 1. å ³éæä»¶çæ§ // 2. éæ¾èµæº // 3. ä¿åç¶æ // 4. éç¥å ¶ä»æå¡ directorLockService.releaseLock(); } } blade-service/blade-mdm/src/main/java/org/springblade/mdm/machineback/controller/DirectoryWatcherController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,78 @@ package org.springblade.mdm.machineback.controller; import org.springblade.mdm.machineback.filewatch.DynamicDirectoryWatcher; import org.springblade.mdm.machineback.filewatch.FileLockChecker; import org.springblade.mdm.machineback.filewatch.FileWatcherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; @RestController @RequestMapping("/machineback/file") public class DirectoryWatcherController { private final DynamicDirectoryWatcher directoryWatcher; @Autowired public DirectoryWatcherController(DynamicDirectoryWatcher directoryWatcher) { this.directoryWatcher = directoryWatcher; } @PostMapping("/watch") public String watchDirectory(@RequestParam String directoryPath) { try { Path path = Paths.get(directoryPath); directoryWatcher.addDirectory(path, new SimpleFileChangeListener()); return "Started watching directory: " + directoryPath; } catch (Exception e) { return "Error: " + e.getMessage(); } } @PostMapping("/unwatch") public String unwatchDirectory(@RequestParam String directoryPath) { try { Path path = Paths.get(directoryPath); directoryWatcher.removeDirectory(path); return "Stopped watching directory: " + directoryPath; } catch (Exception e) { return "Error: " + e.getMessage(); } } @PostMapping("/canlock") public String canlock(@RequestParam String filePath) { try { Path path = Paths.get(filePath); boolean comp = FileLockChecker.isFileCompletelyWritten(path); return filePath+ " lock: " + comp; } catch (Exception e) { return "Error: " + e.getMessage(); } } private static class SimpleFileChangeListener implements FileWatcherService.FileChangeListener { @Override public void onFileCreated(Path filePath) { System.out.println("File created: " + filePath); } @Override public void onFileModified(Path filePath) { System.out.println("File modified: " + filePath); //boolean comp = FileLockChecker.isFileCompletelyWritten(filePath); boolean comp = false; try { comp = FileLockChecker.isFileComplete(filePath); } catch (Exception e) { throw new RuntimeException(e); } System.out.println("File FINISHED: " + comp); } @Override public void onFileDeleted(Path filePath) { System.out.println("File deleted: " + filePath); } } } blade-service/blade-mdm/src/main/java/org/springblade/mdm/machineback/entity/MachineBackFile.java
@@ -18,6 +18,7 @@ public static int STATUS_REJECTED = 2; private String programId; private Long ncProgramId; /** * 确认æ¶é´ */ blade-service/blade-mdm/src/main/java/org/springblade/mdm/machineback/filewatch/DirectorLockService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,40 @@ package org.springblade.mdm.machineback.filewatch; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import java.io.File; import java.lang.management.ManagementFactory; @Slf4j @AllArgsConstructor @Service public class DirectorLockService { private final JdbcTemplate jdbcTemplate; public boolean acquireLock() { int affect = 0; try { affect = jdbcTemplate.update( "INSERT INTO mdm_file_locks (lock_id,locked_by, lock_time) " + "VALUES (1,?, CURRENT_TIMESTAMP)",getInstanceId()); } catch (Exception e) { log.info("æä»¶éå®å¤±è´¥ï¼ä¸è¿è¡ç®å½çæ§",e); } return affect > 0; } public void releaseLock() { jdbcTemplate.update( "DELETE FROM mdm_file_locks"); } private String getInstanceId() { // è¿åå½åå®ä¾çå¯ä¸æ è¯ return ManagementFactory.getRuntimeMXBean().getName(); } } blade-service/blade-mdm/src/main/java/org/springblade/mdm/machineback/filewatch/DynamicDirectoryWatcher.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,28 @@ package org.springblade.mdm.machineback.filewatch; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.file.Path; import java.util.Set; @Service public class DynamicDirectoryWatcher { private final FileWatcherService fileWatcherService; @Autowired public DynamicDirectoryWatcher(FileWatcherService fileWatcherService) { this.fileWatcherService = fileWatcherService; } public void addDirectory(Path directory, FileWatcherService.FileChangeListener listener) throws Exception { fileWatcherService.watchDirectory(directory, listener); } public void removeDirectory(Path directory) throws Exception { fileWatcherService.stopWatching(directory); } public Set<Path> getWatchedDirectories() { return null; //return fileWatcherService.getWatchedDirectories(); } } blade-service/blade-mdm/src/main/java/org/springblade/mdm/machineback/filewatch/FileLockChecker.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,43 @@ package org.springblade.mdm.machineback.filewatch; import java.io.*; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.Files; import java.nio.file.Path; /* çæ§æä»¶æ¯å¦ä¼ è¾å®æï¼ä½¿ç¨å¯å¦é宿¥å¤æï¼ */ public class FileLockChecker { public static boolean isFileCompletelyWritten(Path file) { try (RandomAccessFile raf = new RandomAccessFile(file.toFile(), "rw"); FileChannel channel = raf.getChannel()) { // å°è¯è·åç¬å é FileLock lock = channel.tryLock(); if (lock != null) { lock.release(); // 妿è½è·åéï¼è¯´ææä»¶ä¸å被åå ¥ return true; } return false; } catch (Exception e) { // 妿åçå¼å¸¸ï¼å¯è½æä»¶ä»å¨è¢«åå ¥ return false; } } /** * æä»¶æ¯å¦ä¼ è¾å®æï¼éç¨ååæä»¶å¤§å°æ¯å¯¹æ¹æ³ï¼ * @param file * @return * @throws IOException * @throws InterruptedException */ public static boolean isFileComplete(Path file) throws IOException, InterruptedException { long initialSize = Files.size(file); Thread.sleep(3000); // çå¾ 1ç§ long currentSize = Files.size(file); return initialSize == currentSize; } } blade-service/blade-mdm/src/main/java/org/springblade/mdm/machineback/filewatch/FileWatcherService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,97 @@ package org.springblade.mdm.machineback.filewatch; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.*; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static java.nio.file.StandardWatchEventKinds.*; @Service public class FileWatcherService { private final ExecutorService executor = Executors.newCachedThreadPool(); private final Map<Path, WatchService> watchServices = new HashMap<>(); private final Map<Path, FileChangeListener> listeners = new HashMap<>(); public interface FileChangeListener { void onFileCreated(Path filePath); void onFileModified(Path filePath); void onFileDeleted(Path filePath); } public void watchDirectory(Path directory, FileChangeListener listener) throws IOException { if (!Files.isDirectory(directory)) { throw new IllegalArgumentException("Path must be a directory: " + directory); } if (watchServices.containsKey(directory)) { throw new IllegalStateException("Directory is already being watched: " + directory); } WatchService watchService = FileSystems.getDefault().newWatchService(); directory.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE); watchServices.put(directory, watchService); listeners.put(directory, listener); executor.submit(() -> { try { while (true) { WatchKey key = watchService.take(); for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); @SuppressWarnings("unchecked") WatchEvent<Path> ev = (WatchEvent<Path>) event; Path fileName = ev.context(); Path fullPath = directory.resolve(fileName); FileChangeListener currentListener = listeners.get(directory); if (currentListener == null) break; if (kind == ENTRY_CREATE) { currentListener.onFileCreated(fullPath); } else if (kind == ENTRY_MODIFY) { currentListener.onFileModified(fullPath); } else if (kind == ENTRY_DELETE) { currentListener.onFileDeleted(fullPath); } } boolean valid = key.reset(); if (!valid) { break; } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ClosedWatchServiceException e) { // Service was closed, exit normally } }); } public void stopWatching(Path directory) throws IOException { WatchService watchService = watchServices.remove(directory); listeners.remove(directory); if (watchService != null) { watchService.close(); } } public void shutdown() { executor.shutdownNow(); watchServices.values().forEach(watchService -> { try { watchService.close(); } catch (IOException e) { // Ignore on shutdown } }); watchServices.clear(); listeners.clear(); } } blade-service/blade-mdm/src/main/java/org/springblade/mdm/machineback/filewatch/MachineFileBackListener.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,57 @@ package org.springblade.mdm.machineback.filewatch; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springblade.mdm.machineback.entity.MachineBackFile; import org.springblade.mdm.machineback.service.MachineBackFileService; import org.springblade.mdm.program.entity.NcProgram; import org.springblade.mdm.program.service.NcProgramService; import java.io.IOException; import java.nio.file.Path; @Slf4j public class MachineFileBackListener implements FileWatcherService.FileChangeListener{ private final MachineBackFileService machineBackFileService; private final NcProgramService ncProgramService; public MachineFileBackListener(MachineBackFileService backService, NcProgramService aNcProgramService) { this.machineBackFileService = backService; this.ncProgramService = aNcProgramService; } @Override public void onFileCreated(Path filePath) { log.info("æä»¶å建{}",filePath); } @Override public void onFileModified(Path filePath) { //æä»¶ä¿®æ¹ try { if(FileLockChecker.isFileComplete(filePath)){ log.info("æä»¶ä¼ è¾å®æ{}",filePath); MachineBackFile backFile = new MachineBackFile(); String programName = filePath.getFileName().toFile().getName(); NcProgram prog = ncProgramService.getByName(programName); if(prog == null){ log.warn("æ´æ°çæä»¶æ æ³å¹é å°æ°æ§ç¨åº,{}",filePath); return; } backFile.setNcProgramId(prog.getId()); machineBackFileService.save(backFile); }else{ log.warn("æä»¶ä¼ è¾ä¸ï¼åç»åæä½{}",filePath); } } catch (IOException e) { throw new RuntimeException(e); } catch (InterruptedException e) { log.error("sleepåºé"); } } @Override public void onFileDeleted(Path filePath) { log.info("æä»¶å é¤{}",filePath); } } blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcProgramController.java
@@ -121,12 +121,12 @@ return R.data(approveRecordService.listByNcProgramId(ncProgramId)); } /* @PostMapping("/send") @Operation(summary = "ç¨åºä¸å", description = "å·¥æ§ç½æ°æ§ç¨åºä¸åï¼åéå°æºåºé ç½®çä¸åç®å½ï¼") @Operation(summary = "ç¨åºä¸å", description = "å·¥æ§ç½æ°æ§ç¨åºä¸åï¼åéå°æºåºé ç½®çä¸åç®å½ï¼,æ ¹æ®id") public R<List<NcProgramVO>> send(@Parameter(description="æå±èç¹ID")@RequestParam Long id) { return null;//R.data(ncProcessProgRefService.listByProcess(processInstanceId)); } }*/ @PostMapping("/send-to-machine-by-nodeid") @Operation(summary = "ç¨åºä¸å", description = "ä¸åç»æºåºè®¾å®çç®å½") blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcProgramExportDNCController.java
@@ -11,6 +11,7 @@ import org.springblade.core.log.exception.ServiceException; import org.springblade.core.tenant.annotation.NonDS; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.DateUtil; import org.springblade.mdm.commons.vo.IdsVO; import org.springblade.mdm.program.service.NcProgramApprovedService; import org.springblade.mdm.program.service.NcProgramExportDNCService; @@ -52,7 +53,8 @@ throw new ServiceException("æªéæ©æä»¶å¯¼åº"); } try { response.setHeader("Content-Disposition", "attachment; filename=dnc-t.zip"); String filename = "todncexp-"+ DateUtil.format(DateUtil.now(), "yyyyMMddHHmm")+".zip"; response.setHeader("Content-Disposition", "attachment; filename="+filename); response.setContentType("application/octet-stream"); ncProgramExportDNCService.exportDnc(vo.getIds(),response.getOutputStream()); } catch (IOException e) { blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProcessProgRefMapper.xml
@@ -4,7 +4,7 @@ <select id="listByProcess" resultType="org.springblade.mdm.program.vo.NcProgramVO"> select p.id,p.name,url,code from mdm_process_prog_ref r join mdm_nc_program p on r.nc_program_id=p.id select p.id,p.name,p.machine_code,url,code from mdm_process_prog_ref r join mdm_nc_program p on r.nc_program_id=p.id where process_instance_id=#{processInstanceId} and p.is_deleted=0 </select> </mapper> blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/MdmProgramImportService.java
@@ -238,25 +238,25 @@ JSONArray jsonArray = JSONArray.parseArray(jsonStr); for(int i=0;i<jsonArray.size();i++){ JSONObject jsonObject = jsonArray.getJSONObject(i); NcProgram d = new NcProgram(); d.setId(jsonObject.getLong("id")); d.setName(jsonObject.getString("name")); NcProgram prog = new NcProgram(); prog.setId(jsonObject.getLong("id")); prog.setName(jsonObject.getString("name")); d.setCode(jsonObject.getString("code")); d.setDescription(jsonObject.getString("description")); d.setCategory(jsonObject.getString("category")); d.setBindNcNodeId(jsonObject.getLong("bindNcNodeId")); d.setIsLastEdition(jsonObject.getInteger("isLastEdition")); d.setIsLocked(jsonObject.getInteger("isLocked")); d.setIsTest(jsonObject.getInteger("isTest")); d.setMachineCode(jsonObject.getString("machineCode")); d.setNcNodeId(jsonObject.getLong("ncNodeId")); d.setDrawingNo(jsonObject.getString("drawingNo")); d.setProcessEdition(jsonObject.getString("processEdition")); prog.setCode(jsonObject.getString("code")); prog.setDescription(jsonObject.getString("description")); prog.setCategory(jsonObject.getString("category")); prog.setBindNcNodeId(jsonObject.getLong("bindNcNodeId")); prog.setIsLastEdition(jsonObject.getInteger("isLastEdition")); prog.setIsLocked(jsonObject.getInteger("isLocked")); prog.setIsTest(jsonObject.getInteger("isTest")); prog.setMachineCode(jsonObject.getString("machineCode")); prog.setNcNodeId(jsonObject.getLong("ncNodeId")); prog.setDrawingNo(jsonObject.getString("drawingNo")); prog.setProcessEdition(jsonObject.getString("processEdition")); setBaseProperties(d,jsonObject); setBaseProperties(prog,jsonObject); progList.add(d); progList.add(prog); } } @@ -296,6 +296,7 @@ record.setUserNickname(jsonObject.getString("userNickname")); record.setOperateResult(jsonObject.getString("operateResult")); record.setOperateTime(jsonObject.getDate("operateTime")); record.setComment(jsonObject.getString("comment")); setBaseProperties(record,jsonObject); recordList.add(record); blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExportDNCService.java
@@ -130,6 +130,7 @@ recObj.put("code", program.getCode()); recObj.put("ossName",program.getOssName()); recObj.put("isTextFile",program.getIsTextFile()); recObj.put("isLastEdition",program.getIsLastEdition()); recObj.put("category",program.getCategory()); recObj.put("description",program.getDescription()); recObj.put("name",program.getName()); @@ -196,11 +197,11 @@ ArrayList<Long> exportNodeIdList = new ArrayList<>(); for(NcProgram program : programs){ JSONObject recObj = new JSONObject(); if(!exportNodeIdList.contains(program.getNcNodeId())){ exportNodeIdList.add(program.getNcNodeId()); //JSONObject recObj = new JSONObject(); if(!exportNodeIdList.contains(program.getBindNcNodeId())){ exportNodeIdList.add(program.getBindNcNodeId()); } NcNode ncNode = ncNodeService.getById(program.getNcNodeId()); NcNode ncNode = ncNodeService.getById(program.getBindNcNodeId());//ä»ç»å®çèç¹æ¬èº«å¼å§å¯¼åº if(StringUtils.isNotEmpty(ncNode.getParentIds())){ List<Long> pids = Func.toLongList(ncNode.getParentIds()); blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramService.java
@@ -159,6 +159,10 @@ node.setDrawingNo(uploadVO.getDrawingNo()); node.setProcessName(uploadVO.getProcessName()); NcNode parentNode = nodeService.getById(uploadVO.getNodeId()); node.setParentIds(parentNode.getParentIds()+","+uploadVO.getNodeId()); //uploadVO.getre //node.setDescription(uploadVO.getDrawingNo()); nodeService.save(node); prog.setBindNcNodeId(node.getId()); @@ -318,4 +322,17 @@ return progOpt.orElse(null); } /** * æ ¹æ®ç¨åºåç§°è·åææ°çç¨åºæ°æ® * @param name ç¨åºåç§° * @return */ public NcProgram getByName(String name) {LambdaQueryWrapper<NcProgram> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(NcProgram::getName, name); wrapper.eq(NcProgram::getIsLastEdition,1); Optional<NcProgram> progOpt = this.getOneOpt(wrapper); return progOpt.orElse(null); } }