package org.springblade.mdm.basesetting.machine.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.MybatisUtils; import org.apache.commons.lang3.StringUtils; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BizServiceImpl; import org.springblade.core.mp.support.Condition; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.SpringUtil; import org.springblade.mdm.basesetting.machine.entity.Machine; import org.springblade.mdm.basesetting.machine.mapper.MachineMapper; import org.springblade.mdm.basesetting.machine.vo.MachineQueryVO; import org.springblade.mdm.basesetting.machine.vo.MachineSaveVO; import org.springblade.mdm.basesetting.machine.vo.MachineVO; import org.springblade.mdm.basesetting.producedivision.service.MdmDeptService; import org.springblade.mdm.commons.service.MachineDirTranslator; import org.springblade.mdm.commons.service.ParamService; import org.springblade.mdm.machinefile.entity.MachineFile; import org.springblade.mdm.machinefile.filewatch.DynamicDirectoryWatcher; import org.springblade.mdm.machinefile.filewatch.MachineFileChangeListener; import org.springblade.mdm.machinefile.filewatch.WatchInfo; import org.springblade.mdm.machinefile.service.MachineFileService; import org.springblade.mdm.program.service.ProgramAnnotationService; import org.springblade.system.feign.ISysClient; import org.springblade.system.pojo.entity.Dept; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Optional; @Service public class MachineService extends BizServiceImpl { @Autowired private ISysClient sysClient; @Autowired private DynamicDirectoryWatcher dynamicDirectoryWatcher; @Autowired private ParamService paramService; @Autowired private MachineDirTranslator machineDirTranslator; @Transactional(rollbackFor = Exception.class) public void saveMachine(MachineSaveVO vo) throws IOException { checkMachine(vo); if(existsByCode(vo.getCode(),null)){ throw new ServiceException("机床编码已存在:"+vo.getCode()); } if(existsByEquipmentCode(vo.getEquipmentCode(),null)){ throw new ServiceException("设备编号已存在:"+vo.getEquipmentCode()); } Machine machine = new Machine(); BeanUtil.copyProperties(vo, machine); machine.setId(null); this.save(machine); makeMachineDirs(machine); addDirWatcher(machine); } void makeMachineDirs(Machine machine) throws IOException { Path dir; if(StringUtils.isNotBlank(machine.getProgSendDir())){ createDirIsNotExists(machineDirTranslator.trans(machine.getProgSendDir())); } if(StringUtils.isNotBlank(machineDirTranslator.trans(machine.getProgReceiveDir()))){ createDirIsNotExists(machineDirTranslator.trans(machine.getProgReceiveDir())); } if(StringUtils.isNotBlank(machineDirTranslator.trans(machine.getProgTempDir()))){ createDirIsNotExists(machineDirTranslator.trans(machine.getProgTempDir())); } } void createDirIsNotExists(String pathdir) throws IOException { Path dir = Paths.get(pathdir); if(!Files.exists(dir)){ Files.createDirectories(dir); } } void addDirWatcher(Machine machine){ String type = paramService.networkType(); if(type.equals(ParamService.NETWORK_TYPE_SHEMI)){ //涉密网不需要监控目录 return; } try { MachineFileService machineFileService = SpringUtil.getBean(MachineFileService.class); ProgramAnnotationService annoService = SpringUtil.getBean(ProgramAnnotationService.class); if(StringUtils.isNotBlank(machine.getProgSendDir())) { String sendDir = machineDirTranslator.trans(machine.getProgSendDir()); WatchInfo watchInfoSend = new WatchInfo(); watchInfoSend.setMachine(machine); watchInfoSend.setDirType(MachineFile.DIR_TYPE_SEND); watchInfoSend.setPath(sendDir); Path path = Paths.get(sendDir); if(!dynamicDirectoryWatcher.containsPath(path)) { dynamicDirectoryWatcher.addDirectory(path, new MachineFileChangeListener(machineFileService, annoService, watchInfoSend)); } } if(StringUtils.isNotBlank(machine.getProgReceiveDir())) { String recDir = machineDirTranslator.trans(machine.getProgReceiveDir()); WatchInfo watchInfoRec = new WatchInfo(); watchInfoRec.setMachine(machine); watchInfoRec.setDirType(MachineFile.DIR_TYPE_REC); watchInfoRec.setPath(recDir); Path path = Paths.get(recDir); if(!dynamicDirectoryWatcher.containsPath(path)) { dynamicDirectoryWatcher.addDirectory(path, new MachineFileChangeListener(machineFileService, annoService, watchInfoRec)); } } if(StringUtils.isNotBlank(machine.getProgTempDir())) { String tempDir = machineDirTranslator.trans(machine.getProgTempDir()); WatchInfo watchInfoTemp = new WatchInfo(); watchInfoTemp.setMachine(machine); watchInfoTemp.setDirType(MachineFile.DIR_TYPE_TEMP); watchInfoTemp.setPath(tempDir); Path path = Paths.get(machine.getProgTempDir()); if(!dynamicDirectoryWatcher.containsPath(path)) { dynamicDirectoryWatcher.addDirectory(path, new MachineFileChangeListener(machineFileService, annoService, watchInfoTemp)); } } } catch (Exception e) { log.error("增加机床监控异常",e); throw new RuntimeException(e); } } /** * 检查机床录入数据 * @param vo 录入的表单数据VO */ void checkMachine(MachineSaveVO vo){ if(Func.isEmpty(vo.getCode())){ throw new ServiceException("机床编码不能为空"); } if(Func.isEmpty(vo.getName())){ throw new ServiceException("机床类型不能为空"); } if(Func.isEmpty(vo.getMachineGroupCode())){ throw new ServiceException("所属组织不能为空"); } if(Func.isEmpty(vo.getMachineSpec())){ throw new ServiceException("机床类型不能为空"); } } /** * 根据机床编码判断机床是否存在 * @param code 机床编码 * @param excludeId 排除id * @return 是否存在 */ boolean existsByCode(String code,Long excludeId){ return this.lambdaQuery().eq(Machine::getCode, code).ne(excludeId!=null,Machine::getId, excludeId).count()>0; } /** * 根据 设备编号判断机床是否存在 * @param equipmentCode 设备编号 * @param excludeId 排除id * @return 是否存在 */ boolean existsByEquipmentCode(String equipmentCode,Long excludeId){ return this.lambdaQuery().eq(Machine::getEquipmentCode, equipmentCode).ne(excludeId!=null,Machine::getId, excludeId).count()>0; } /** * 修改机床信息 * @param vo * @return */ public boolean updateMachine(MachineSaveVO vo) throws Exception { checkMachine(vo); if(existsByCode(vo.getCode(),vo.getId())){ throw new ServiceException("机床编码已存在:"+vo.getCode()); } if(existsByEquipmentCode(vo.getEquipmentCode(),vo.getId())){ throw new ServiceException("设备编号已存在:"+vo.getEquipmentCode()); } Machine machine = this.getById(vo.getId()); Machine machineBak = new Machine(); BeanUtil.copyProperties(machine, machineBak); machine.setMachineSpec(vo.getMachineSpec()); machine.setCode(vo.getCode()); machine.setEquipmentCode(vo.getEquipmentCode()); machine.setName(vo.getName()); machine.setMachineGroupCode(vo.getMachineGroupCode()); machine.setManufacturer(vo.getManufacturer()); machine.setOperator(vo.getOperator()); machine.setControlSystem(vo.getControlSystem()); machine.setOwnerDept(vo.getOwnerDept()); machine.setProgSendDir(vo.getProgSendDir()); machine.setProgReceiveDir(vo.getProgReceiveDir()); machine.setProgTempDir(vo.getProgTempDir()); machine.setStatus(vo.getStatus()); machine.setRemark(vo.getRemark()); machine.setSendDirExpiryHours(vo.getSendDirExpiryHours()); machine.setReceiveDirExpiryHours(vo.getReceiveDirExpiryHours()); boolean updateR = this.updateById(machine); removeDirWatcher(machineBak); addDirWatcher(machine); return updateR; } /** * 去掉目录监控 * @param machine * @throws Exception */ private void removeDirWatcher(Machine machine) throws Exception { String type = paramService.networkType(); if(type.equals(ParamService.NETWORK_TYPE_SHEMI)){ //涉密网不需要监控目录 return; } if(StringUtils.isNotBlank(machine.getProgSendDir())) { dynamicDirectoryWatcher.removeDirectory(Paths.get(machine.getProgSendDir())); } if(StringUtils.isNotBlank(machine.getProgReceiveDir())) { dynamicDirectoryWatcher.removeDirectory(Paths.get(machine.getProgReceiveDir())); } if(StringUtils.isNotBlank(machine.getProgTempDir())) { dynamicDirectoryWatcher.removeDirectory(Paths.get(machine.getProgTempDir())); } } /** * 查询分页 * @param query 查询参数 * @return 分页数据 */ public IPage pageQuery(MachineQueryVO query) { if (query.getDeptId() != null) { R rs = sysClient.getDept(query.getDeptId()); if(rs.isSuccess()){ query.setDeptAncestors(rs.getData().getAncestors()+","+rs.getData().getId()); } } return this.getBaseMapper().pageQuery(Condition.getPage(query), query); } /** * 查询详情 * @param id 机床id * @return */ public MachineVO detail(long id) { Machine machine = this.getById(id); MachineVO vo = new MachineVO(); BeanUtil.copyProperties(machine, vo); return vo; } /** * 产生机床回传结构数据 * @param id */ /* public void genMachineFileBackDirs(Long id) throws IOException { Machine machine = this.getById(id); if(Func.isNotBlank(machine.getProgReceiveDir())){ if(isLegalDirectoryPath(machine.getProgReceiveDir())) { Path path = Paths.get(machine.getProgReceiveDir()); Files.createDirectories(path); }else{ throw new RuntimeException("非法的目录格式"); } } }*/ /** * 判断是否是合法的目录格式 * @param path * @return */ static boolean isLegalDirectoryPath(String path) { // 基础检查 if (path == null || path.trim().isEmpty()) { return false; } // 使用NIO检查路径格式 Path nioPath; try { nioPath = Paths.get(path); if (!nioPath.normalize().toString().equals(path)) { return false; // 路径不规范 } } catch (InvalidPathException ex) { return false; } return true; } /** * 根据机床编码获取机床 * @param machineCode 机床编码 * @return */ public Machine getByCode(String machineCode) { return this.lambdaQuery().eq(Machine::getCode, machineCode).one(); } /** * 获取所有启用状态的机床列表 * @return 机床列表 */ public List getEnableMachines() { return lambdaQuery().eq(Machine::getStatus,Machine.STATUS_ENABLE).list(); } public String escapeSqlWildcard(String value) { if (StringUtils.isBlank(value)) { return value; } return value.replace("\\", "\\\\") .replace("%", "\\%") .replace("_", "\\_"); } /** * 根据下发路径的注释查询机床 * @param sendPathLine 下发路径注释文本 */ public Machine getMachineBySendPathAnnotation(String sendPathLine) { //路径为空,不匹配任何机器 if(StringUtils.isBlank(sendPathLine)){ return null; } //去掉末尾括号(发那科) ,末尾路径分隔符 String oriPath = StringUtils.removeEnd(StringUtils.removeEnd(StringUtils.removeEnd(sendPathLine,")"),"/"),"\\"); String tempPathRepl1 = StringUtils.replace(oriPath,"/","\\");//反斜杠版本的路径 String tempPathRepl2 = StringUtils.replace(oriPath,"\\","/");//正斜杠版本的路径 //去掉前2位可能的注释(*-)。 String sendPath1 = escapeSqlWildcard(StringUtils.trim(StringUtils.substring(tempPathRepl1,2))); String sendPath2 = escapeSqlWildcard(StringUtils.trim(StringUtils.substring(tempPathRepl2,2))); Optional machineOpt = lambdaQuery().eq(Machine::getStatus,Machine.STATUS_ENABLE).and(w -> { w.like(Machine::getProgSendDir,sendPath1).or().like(Machine::getProgSendDir,sendPath2); }).last("limit 1").oneOpt(); return machineOpt.orElse(null); } /** * 根据设备编号查询机床 * @param equipmentCode 设备编号 * @return 机床对象 */ public Machine getByEquipmentCode(String equipmentCode) { return this.lambdaQuery().eq(Machine::getEquipmentCode, equipmentCode).one(); } }