|
|
|
|
@ -4,18 +4,13 @@ import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
|
|
|
|
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
|
|
|
|
|
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
|
|
|
|
|
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.devicecontactmodel.DeviceContactModelDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.devicecontactmodel.DeviceContactModelMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.service.device.DeviceService;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.feedingrecord.vo.FeedingRecordRespVO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.organization.vo.OrgClassEnum;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.organization.vo.OrganizationListReqVO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.organization.vo.OrganizationRespVO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.organization.vo.OrganizationSaveReqVO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.organization.vo.*;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.controller.admin.orgworker.vo.OrgWorkerPageReqVO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.machine.MachineComponentDO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.organization.OrganizationDO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.dataobject.orgworker.OrgWorkerDO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.dal.mysql.organization.OrganizationMapper;
|
|
|
|
|
@ -24,6 +19,7 @@ import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO;
|
|
|
|
|
import cn.iocoder.yudao.module.mes.service.machine.MachineComponentService;
|
|
|
|
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
|
|
|
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
|
|
@ -31,6 +27,7 @@ import org.springframework.validation.annotation.Validated;
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
|
|
@ -55,7 +52,10 @@ public class OrganizationServiceImpl implements OrganizationService {
|
|
|
|
|
private MesNoRedisDAO noRedisDAO;
|
|
|
|
|
@Resource
|
|
|
|
|
private AdminUserApi adminUserApi;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private DeviceContactModelMapper deviceContactModelMapper;
|
|
|
|
|
@Resource
|
|
|
|
|
private DeviceMapper deviceMapper;
|
|
|
|
|
@Override
|
|
|
|
|
public Long createOrganization(OrganizationSaveReqVO createReqVO) {
|
|
|
|
|
// 校验父组织id的有效性
|
|
|
|
|
@ -255,4 +255,320 @@ public class OrganizationServiceImpl implements OrganizationService {
|
|
|
|
|
List<OrganizationDO> list = organizationMapper.selectBatchIds(ids);
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<LineAnalysisTreeDTO.LineNode> deviceParameterAnalysis(String keyword) {
|
|
|
|
|
|
|
|
|
|
//1. 获取产线集合
|
|
|
|
|
OrganizationListReqVO organizationListReqVO = new OrganizationListReqVO();
|
|
|
|
|
List<OrganizationDO> organizationDOS = getOrganizationList(organizationListReqVO);
|
|
|
|
|
List<OrganizationRespVO> organizationRespVOS = buildVOList(organizationDOS);
|
|
|
|
|
if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(organizationRespVOS)) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 获取所有有machineId的产线
|
|
|
|
|
List<Long> machineIds = organizationRespVOS.stream()
|
|
|
|
|
.map(OrganizationRespVO::getMachineId)
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
// 3. 根据machineId查询设备
|
|
|
|
|
List<DeviceDO> allDevices = Collections.emptyList();
|
|
|
|
|
if (!machineIds.isEmpty()) {
|
|
|
|
|
LambdaQueryWrapper<DeviceDO> deviceWrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
deviceWrapper.in(DeviceDO::getId, machineIds)
|
|
|
|
|
.eq(DeviceDO::getIsEnable, true);
|
|
|
|
|
allDevices = deviceMapper.selectList(deviceWrapper);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 获取所有参数
|
|
|
|
|
List<DeviceContactModelDO> allParameters = getAllParameters(allDevices);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 构建映射关系
|
|
|
|
|
Map<Long, DeviceDO> deviceById = allDevices.stream()
|
|
|
|
|
.collect(Collectors.toMap(DeviceDO::getId, Function.identity()));
|
|
|
|
|
|
|
|
|
|
// 6. 构建设备按产线分组的映射
|
|
|
|
|
Map<Long, List<DeviceDO>> devicesByLineId = new HashMap<>();
|
|
|
|
|
for (OrganizationRespVO line : organizationRespVOS) {
|
|
|
|
|
if (line.getMachineId() != null) {
|
|
|
|
|
DeviceDO device = deviceById.get(line.getMachineId());
|
|
|
|
|
if (device != null) {
|
|
|
|
|
devicesByLineId.computeIfAbsent(line.getId(), k -> new ArrayList<>())
|
|
|
|
|
.add(device);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<Long, List<DeviceContactModelDO>> paramsByDeviceId = allParameters.stream()
|
|
|
|
|
.filter(param -> param.getDeviceId() != null)
|
|
|
|
|
.collect(Collectors.groupingBy(DeviceContactModelDO::getDeviceId));
|
|
|
|
|
|
|
|
|
|
// 7. 构建树结构
|
|
|
|
|
return buildTreeStructureWithKeyword(organizationRespVOS, devicesByLineId, paramsByDeviceId,keyword);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
private List<LineAnalysisTreeDTO.LineNode> buildTreeStructureWithKeyword(List<OrganizationRespVO> lines,
|
|
|
|
|
Map<Long, List<DeviceDO>> devicesByLineId,
|
|
|
|
|
Map<Long, List<DeviceContactModelDO>> paramsByDeviceId,
|
|
|
|
|
String keyword) {
|
|
|
|
|
|
|
|
|
|
// 统一处理关键词
|
|
|
|
|
boolean hasKeyword = StringUtils.isNotBlank(keyword);
|
|
|
|
|
String lowerKeyword = hasKeyword ? keyword.toLowerCase() : "";
|
|
|
|
|
|
|
|
|
|
// 记录匹配情况
|
|
|
|
|
Map<Long, Boolean> lineMatchedMap = new HashMap<>();
|
|
|
|
|
Map<Long, Boolean> deviceMatchedMap = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
// 第一遍:分析匹配情况
|
|
|
|
|
for (OrganizationRespVO line : lines) {
|
|
|
|
|
// 产线是否匹配
|
|
|
|
|
boolean lineMatch = !hasKeyword ||
|
|
|
|
|
(line.getName() != null && line.getName().toLowerCase().contains(lowerKeyword));
|
|
|
|
|
lineMatchedMap.put(line.getId(), lineMatch);
|
|
|
|
|
|
|
|
|
|
// 检查该产线的设备
|
|
|
|
|
List<DeviceDO> lineDevices = devicesByLineId.getOrDefault(line.getId(), new ArrayList<>());
|
|
|
|
|
for (DeviceDO device : lineDevices) {
|
|
|
|
|
// 设备是否匹配
|
|
|
|
|
boolean deviceMatch = !hasKeyword ||
|
|
|
|
|
(device.getDeviceName() != null &&
|
|
|
|
|
device.getDeviceName().toLowerCase().contains(lowerKeyword));
|
|
|
|
|
deviceMatchedMap.put(device.getId(), deviceMatch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第二遍:构建树结构
|
|
|
|
|
return lines.stream().map(line -> {
|
|
|
|
|
boolean lineMatch = lineMatchedMap.getOrDefault(line.getId(), false);
|
|
|
|
|
|
|
|
|
|
// 关键修改:如果产线匹配,跳过后续的设备过滤逻辑
|
|
|
|
|
if (hasKeyword && !lineMatch) {
|
|
|
|
|
// 检查产线下是否有匹配的设备或参数
|
|
|
|
|
boolean hasMatchingDeviceOrParam = checkIfLineHasMatchingDeviceOrParam(
|
|
|
|
|
line, devicesByLineId, paramsByDeviceId, lowerKeyword, deviceMatchedMap);
|
|
|
|
|
if (!hasMatchingDeviceOrParam) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取该产线的设备
|
|
|
|
|
List<DeviceDO> lineDevices = devicesByLineId.getOrDefault(line.getId(), new ArrayList<>());
|
|
|
|
|
|
|
|
|
|
// 构建设备节点
|
|
|
|
|
List<LineAnalysisTreeDTO.EquipmentNode> equipmentNodes = lineDevices.stream()
|
|
|
|
|
.map(device -> {
|
|
|
|
|
boolean deviceMatch = deviceMatchedMap.getOrDefault(device.getId(), false);
|
|
|
|
|
|
|
|
|
|
// 关键修改:如果产线匹配,保留所有设备
|
|
|
|
|
if (lineMatch) {
|
|
|
|
|
// 产线匹配时,保留该设备
|
|
|
|
|
List<DeviceContactModelDO> deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>());
|
|
|
|
|
|
|
|
|
|
// 产线匹配时,显示所有参数
|
|
|
|
|
List<LineAnalysisTreeDTO.ParameterNode> parameterNodes = deviceParams.stream()
|
|
|
|
|
.map(this::buildParameterNode)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
return LineAnalysisTreeDTO.EquipmentNode.builder()
|
|
|
|
|
.id(device.getId())
|
|
|
|
|
.name(device.getDeviceName())
|
|
|
|
|
.parameters(parameterNodes)
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 以下为原有逻辑:产线不匹配时的处理
|
|
|
|
|
if (hasKeyword && !deviceMatch) {
|
|
|
|
|
boolean hasMatchingParam = checkIfDeviceHasMatchingParam(
|
|
|
|
|
device, paramsByDeviceId, lowerKeyword);
|
|
|
|
|
if (!hasMatchingParam) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<DeviceContactModelDO> deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>());
|
|
|
|
|
|
|
|
|
|
// 构建参数节点
|
|
|
|
|
List<LineAnalysisTreeDTO.ParameterNode> parameterNodes = deviceParams.stream()
|
|
|
|
|
.filter(param -> {
|
|
|
|
|
if (!hasKeyword) {
|
|
|
|
|
return true; // 没有关键词,显示所有
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 有关键词时:
|
|
|
|
|
// 如果设备匹配,显示所有参数
|
|
|
|
|
if (deviceMatch) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 否则,只显示匹配的参数
|
|
|
|
|
return isParameterMatch(param, lowerKeyword);
|
|
|
|
|
})
|
|
|
|
|
.map(this::buildParameterNode)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
return LineAnalysisTreeDTO.EquipmentNode.builder()
|
|
|
|
|
.id(device.getId())
|
|
|
|
|
.name(device.getDeviceName())
|
|
|
|
|
.parameters(parameterNodes)
|
|
|
|
|
.build();
|
|
|
|
|
})
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.filter(equipmentNode -> !lineMatch || !equipmentNode.getParameters().isEmpty()) // 修改过滤条件
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
// 构建设备节点
|
|
|
|
|
return LineAnalysisTreeDTO.LineNode.builder()
|
|
|
|
|
.id(line.getId())
|
|
|
|
|
.name(line.getName())
|
|
|
|
|
.equipments(equipmentNodes)
|
|
|
|
|
.build();
|
|
|
|
|
})
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.filter(lineNode -> !hasKeyword || lineMatchedMap.getOrDefault(lineNode.getId(), false) || !lineNode.getEquipments().isEmpty())
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查产线下是否有匹配的设备或参数
|
|
|
|
|
*/
|
|
|
|
|
private boolean checkIfLineHasMatchingDeviceOrParam(OrganizationRespVO line,
|
|
|
|
|
Map<Long, List<DeviceDO>> devicesByLineId,
|
|
|
|
|
Map<Long, List<DeviceContactModelDO>> paramsByDeviceId,
|
|
|
|
|
String lowerKeyword,
|
|
|
|
|
Map<Long, Boolean> deviceMatchedMap) {
|
|
|
|
|
|
|
|
|
|
List<DeviceDO> lineDevices = devicesByLineId.getOrDefault(line.getId(), new ArrayList<>());
|
|
|
|
|
|
|
|
|
|
for (DeviceDO device : lineDevices) {
|
|
|
|
|
// 检查设备是否匹配
|
|
|
|
|
boolean deviceMatch = deviceMatchedMap.getOrDefault(device.getId(), false);
|
|
|
|
|
if (deviceMatch) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查设备下的参数是否匹配
|
|
|
|
|
List<DeviceContactModelDO> deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>());
|
|
|
|
|
boolean hasMatchingParam = deviceParams.stream()
|
|
|
|
|
.anyMatch(param -> isParameterMatch(param, lowerKeyword));
|
|
|
|
|
if (hasMatchingParam) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查设备下是否有匹配的参数
|
|
|
|
|
*/
|
|
|
|
|
private boolean checkIfDeviceHasMatchingParam(DeviceDO device,
|
|
|
|
|
Map<Long, List<DeviceContactModelDO>> paramsByDeviceId,
|
|
|
|
|
String lowerKeyword) {
|
|
|
|
|
|
|
|
|
|
List<DeviceContactModelDO> deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>());
|
|
|
|
|
return deviceParams.stream()
|
|
|
|
|
.anyMatch(param -> isParameterMatch(param, lowerKeyword));
|
|
|
|
|
}
|
|
|
|
|
private List<LineAnalysisTreeDTO.LineNode> buildTreeStructure(List<OrganizationRespVO> lines,
|
|
|
|
|
Map<Long, List<DeviceDO>> devicesByLineId,
|
|
|
|
|
Map<Long, List<DeviceContactModelDO>> paramsByDeviceId) {
|
|
|
|
|
return lines.stream().map(line -> {
|
|
|
|
|
LineAnalysisTreeDTO.LineNode lineNode = LineAnalysisTreeDTO.LineNode.builder()
|
|
|
|
|
.id(line.getId())
|
|
|
|
|
.name(line.getName())
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
// 获取该产线的设备
|
|
|
|
|
List<DeviceDO> lineDevices = devicesByLineId.getOrDefault(line.getId(), new ArrayList<>());
|
|
|
|
|
|
|
|
|
|
// 构建设备节点
|
|
|
|
|
List<LineAnalysisTreeDTO.EquipmentNode> equipmentNodes = lineDevices.stream()
|
|
|
|
|
.map(device -> buildEquipmentNode(device, paramsByDeviceId))
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
lineNode.setEquipments(equipmentNodes);
|
|
|
|
|
return lineNode;
|
|
|
|
|
}).collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 判断参数是否匹配关键词
|
|
|
|
|
*/
|
|
|
|
|
private boolean isParameterMatch(DeviceContactModelDO param, String lowerKeyword) {
|
|
|
|
|
if (StringUtils.isBlank(lowerKeyword)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (param.getAttributeName() != null && param.getAttributeName().toLowerCase().contains(lowerKeyword)) ||
|
|
|
|
|
(param.getAttributeCode() != null && param.getAttributeCode().toLowerCase().contains(lowerKeyword));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 构建设备节点
|
|
|
|
|
*/
|
|
|
|
|
private LineAnalysisTreeDTO.EquipmentNode buildEquipmentNode(DeviceDO device,
|
|
|
|
|
Map<Long, List<DeviceContactModelDO>> paramsByDeviceId) {
|
|
|
|
|
LineAnalysisTreeDTO.EquipmentNode equipmentNode = LineAnalysisTreeDTO.EquipmentNode.builder()
|
|
|
|
|
.id(device.getId())
|
|
|
|
|
.name(device.getDeviceName())
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
// 获取设备参数
|
|
|
|
|
List<DeviceContactModelDO> deviceParams =
|
|
|
|
|
paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>());
|
|
|
|
|
|
|
|
|
|
// 构建参数节点
|
|
|
|
|
List<LineAnalysisTreeDTO.ParameterNode> parameterNodes = deviceParams.stream()
|
|
|
|
|
.map(this::buildParameterNode)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
equipmentNode.setParameters(parameterNodes);
|
|
|
|
|
return equipmentNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 构建参数节点
|
|
|
|
|
*/
|
|
|
|
|
private LineAnalysisTreeDTO.ParameterNode buildParameterNode(DeviceContactModelDO param) {
|
|
|
|
|
return LineAnalysisTreeDTO.ParameterNode.builder()
|
|
|
|
|
.id(param.getId())
|
|
|
|
|
.name(param.getAttributeName())
|
|
|
|
|
.code(param.getAttributeCode())
|
|
|
|
|
.type(param.getAttributeType())
|
|
|
|
|
.dataType(param.getDataType())
|
|
|
|
|
.unit(param.getDataUnit())
|
|
|
|
|
.ratio(param.getRatio())
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<DeviceContactModelDO> getAllParameters(List<DeviceDO> devices) {
|
|
|
|
|
|
|
|
|
|
if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(devices)) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<Long> deviceIds = devices.stream()
|
|
|
|
|
.map(DeviceDO::getId)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
LambdaQueryWrapper<DeviceContactModelDO> wrapper = new LambdaQueryWrapper<>();
|
|
|
|
|
wrapper.in(DeviceContactModelDO::getDeviceId, deviceIds)
|
|
|
|
|
.orderByAsc(DeviceContactModelDO::getSort); // 按排序字段排序
|
|
|
|
|
|
|
|
|
|
List<DeviceContactModelDO> result = deviceContactModelMapper.selectList(wrapper);
|
|
|
|
|
|
|
|
|
|
// 调试日志
|
|
|
|
|
System.out.println("查询条件: 设备IDs=" + deviceIds);
|
|
|
|
|
System.out.println("查询结果数量: " + result.size());
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|