diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java index f7674579f7..90ca470c1b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java @@ -230,8 +230,11 @@ public class DeviceController { return success(deviceService.getDeviceAttribute(id)); } - - + @GetMapping("/devicePointList") + @PreAuthorize("@ss.hasPermission('iot:device:query')") + public CommonResult> devicePointList() { + return success( deviceService.devicePointList()); + } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DevicePointRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DevicePointRespVO.java new file mode 100644 index 0000000000..5d7359a35b --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DevicePointRespVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device.vo; + + +import cn.iocoder.yudao.module.iot.dal.devicecontactmodel.DeviceContactModelDO; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +@Schema(description = "管理后台 - 设备参数集合列表 Resp VO") +@Data +@ToString(callSuper = true) +public class DevicePointRespVO { + + @Schema(description = "设备Id") + private Long deviceId; + + @Schema(description = "设备名称") + private String deviceName; + + @Schema(description = "子集参数列表") + private List contactModelDOList; + + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java index b04f2d8534..a882bc6e11 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java @@ -125,4 +125,5 @@ public interface DeviceService { Map> createDeviceDataMap(Long deviceId); + List devicePointList(); } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java index d00a25d90f..c91206f06d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java @@ -27,10 +27,12 @@ import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceAttributeMapper; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; @@ -55,6 +57,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; */ @Service @Validated +@Slf4j public class DeviceServiceImpl implements DeviceService { @Resource @@ -307,19 +310,45 @@ public class DeviceServiceImpl implements DeviceService { resultMap.put(recordId, recordInfoMap); } else { // 如果记录没有ID,可以记录日志或使用其他策略(如生成临时ID),这里简单跳过 - System.err.println("警告:发现一条数据记录缺少ID,已跳过。"); + log.error("发现一条数据记录缺少ID,已跳过"); } } } } catch (Exception e) { // 异常处理 - System.err.println("处理设备" + deviceId + "的数据时发生异常: " + e.getMessage()); - // 可以选择在异常时返回空Map,或包含错误信息的特殊Map,根据业务需求决定 + log.error("处理设备" + deviceId + "的数据时发生异常: ", e.getMessage()); + return new HashMap<>(); } return resultMap; } + @Override + public List devicePointList() { + + List devicePointRespVOList = new ArrayList<>(); + List deviceDOS = deviceMapper.selectList(Wrappers.lambdaQuery().orderByDesc(DeviceDO::getCreateTime)); + if (deviceDOS.isEmpty()){ + return devicePointRespVOList; + } + for (DeviceDO deviceDO : deviceDOS) { + DevicePointRespVO devicePointRespVO = new DevicePointRespVO(); + devicePointRespVO.setDeviceId(deviceDO.getId()); + devicePointRespVO.setDeviceName(deviceDO.getDeviceName()); + + List deviceContactModelDOS = deviceContactModelMapper.selectList( + Wrappers.lambdaQuery() + .eq(DeviceContactModelDO::getDeviceId, deviceDO.getId())); + + if (!deviceContactModelDOS.isEmpty()){ + devicePointRespVO.setContactModelDOList(deviceContactModelDOS); + } + devicePointRespVOList.add(devicePointRespVO); + + } + return devicePointRespVOList; + } + @Override public Long createDeviceAttribute(DeviceAttributeDO deviceAttribute) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java index c52ccc51c9..e7214d358c 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.taosdata.jdbc.utils.BlobUtil; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import org.springframework.dao.EmptyResultDataAccessException; @@ -22,6 +23,7 @@ import java.text.SimpleDateFormat; import java.util.*; @Service +@Slf4j public class TDengineService { @Resource private JdbcTemplate jdbcTemplate; @@ -374,11 +376,9 @@ public class TDengineService { return result; } }); - } catch (EmptyResultDataAccessException e) { - return Collections.singletonList(createEmptyResult(id)); } catch (Exception e) { - System.err.println("查询设备" + id + "的最新数据时发生异常: " + e.getMessage()); - e.printStackTrace(); + log.error("查询设备" + id + "的最新数据时发生异常", e); +// e.printStackTrace(); return Collections.singletonList(createEmptyResult(id)); } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/devicemodelattribute/DeviceModelAttributeServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/devicemodelattribute/DeviceModelAttributeServiceImpl.java index 207f60c22f..0e71443ec8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/devicemodelattribute/DeviceModelAttributeServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/devicemodelattribute/DeviceModelAttributeServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.dal.mysql.deviceattributetype.DeviceAttribute import cn.iocoder.yudao.module.iot.service.device.TDengineService; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -36,6 +37,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; */ @Service @Validated +@Slf4j public class DeviceModelAttributeServiceImpl implements DeviceModelAttributeService { @Resource @@ -170,7 +172,10 @@ public class DeviceModelAttributeServiceImpl implements DeviceModelAttributeServ } } catch (Exception e) { - throw new RuntimeException("处理设备数据时发生异常", e); + log.error(e.getMessage()); +// e.printStackTrace(); +// throw new RuntimeException("处理设备数据时发生异常", e); + return new ArrayList<>(); } diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index 09de478d44..e4838c7b6b 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -18,6 +18,7 @@ public interface ErrorCodeConstants { ErrorCode BOM_NOT_EXISTS = new ErrorCode(5_001, "产品BOM不存在"); ErrorCode BOM_EXISTS = new ErrorCode(5_002, "产品BOM已存在"); ErrorCode ORGANIZATION_NOT_EXISTS = new ErrorCode(5_0011, "产线工位不存在"); + ErrorCode ORGANIZATION_ID_NOT_EXISTS = new ErrorCode(5_0011, "产线工位不存在"); ErrorCode ORGANIZATION_EXITS_CHILDREN = new ErrorCode(5_0012, "存在存在子产线工位,无法删除"); ErrorCode ORGANIZATION_PARENT_NOT_EXITS = new ErrorCode(5_0013,"父级产线工位不存在"); ErrorCode ORGANIZATION_PARENT_ERROR = new ErrorCode(5_0014, "不能设置自己为父产线工位"); diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/EnergyDeviceController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/EnergyDeviceController.java index 138cdb8109..e5f422db5a 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/EnergyDeviceController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/EnergyDeviceController.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDeviceConsumptionReqVO; import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDevicePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDeviceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDeviceSaveReqVO; @@ -24,6 +25,7 @@ import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -97,12 +99,11 @@ public class EnergyDeviceController { BeanUtils.toBean(list, EnergyDeviceRespVO.class)); } - @PostMapping("/queryDataRecords") + @GetMapping("/queryDataRecords") @Operation(summary = "查询数据记录") @PreAuthorize("@ss.hasPermission('mes:energy-device:create')") - public CommonResult> queryDataRecords(@RequestParam(name = "startTime", required = false ) String startTime, - @RequestParam(name = "endTime", required = false ) String endTime) { - return success(energyDeviceService.queryDataRecords(startTime,endTime)); + public CommonResult> queryDataRecords(@Valid EnergyDeviceConsumptionReqVO deviceConsumptionReqVO) { + return success(energyDeviceService.queryDataRecords(deviceConsumptionReqVO)); } diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/vo/EnergyDeviceConsumptionReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/vo/EnergyDeviceConsumptionReqVO.java new file mode 100644 index 0000000000..d5aead46bc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/vo/EnergyDeviceConsumptionReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 能耗管理/能耗报表 Request VO") +@Data +public class EnergyDeviceConsumptionReqVO { + + @Schema(description = "表名称") + private String name; + + @Schema(description = "所属区域") + private Long orgId; + + @Schema(description = "开始时间") + private String startTime; + + @Schema(description = "结束时间") + private String endTime; + + +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/vo/EnergyDeviceRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/vo/EnergyDeviceRespVO.java index a71495d550..a564d1bff6 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/vo/EnergyDeviceRespVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/energydevice/vo/EnergyDeviceRespVO.java @@ -100,7 +100,7 @@ public class EnergyDeviceRespVO { @ExcelProperty("子列表点位参数值") private Map sublistPointList; - @Schema(description = "列表") - Map> operationRulesVOMap; + @Schema(description = "点位差值列表") + private Map operationRulesVOMap; } \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/OrganizationController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/OrganizationController.java index 5e977f66fc..f9be752d2a 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/OrganizationController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/OrganizationController.java @@ -4,10 +4,7 @@ import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.module.mes.controller.admin.organization.vo.LineAnalysisTreeDTO; -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.dal.dataobject.organization.OrganizationDO; import cn.iocoder.yudao.module.mes.service.organization.OrganizationService; import io.swagger.v3.oas.annotations.Operation; @@ -98,10 +95,22 @@ public class OrganizationController { @GetMapping("/deviceParameterAnalysis") @Operation(summary = "设备运行参数分析") @PreAuthorize("@ss.hasPermission('iot:device:query')") - public CommonResult> deviceParameterAnalysis(@RequestParam(value = "keyword", required = false) String keyword) { - List list = organizationService.deviceParameterAnalysis(keyword); + public CommonResult> deviceParameterAnalysis(@RequestParam(value = "keyword", required = false) String keyword, + @RequestParam(value = "showDevices") Integer showDevices + ) { + List list = organizationService.deviceParameterAnalysis(keyword,showDevices); return success(list); } +// +// @GetMapping("/getParametersById") +// @Operation(summary = "根据产线Id获取点位参数") +// @Parameter(name = "id", description = "编号", required = true, example = "1024") +// //@PreAuthorize("@ss.hasPermission('mes:organization:query')") +// public CommonResult> getParametersById(@RequestParam("id") Long id) { +// List organization = organizationService.getDeviceParametersByOrganizationId(id); +// return success(organization); +// } + } \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/DeviceParametersDTO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/DeviceParametersDTO.java new file mode 100644 index 0000000000..eb127ad652 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/DeviceParametersDTO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.organization.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeviceParametersDTO { + /** + * 设备ID + */ + private Long deviceId; + + /** + * 设备名称 + */ + private String deviceName; + + /** + * 设备编码(可选) + */ + private String deviceCode; + + /** + * 设备类型(可选) + */ + private String deviceType; + + /** + * 设备状态(可选) + */ + private String deviceStatus; + + /** + * 参数列表 + */ + private List parameters; +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/LineAnalysisTreeDTO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/LineAnalysisTreeDTO.java index b897c9ed77..665bdf77a0 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/LineAnalysisTreeDTO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/LineAnalysisTreeDTO.java @@ -27,8 +27,12 @@ public class LineAnalysisTreeDTO { public static class LineNode { private Long id; // 产线ID private String name; // 产线名称 + private String orgClass; // 组织等级 private Long parentId; - private List equipments = new ArrayList<>(); +// private List equipments = new ArrayList<>(); + private List equipments; + private List children; + } // 设备节点 @@ -39,7 +43,7 @@ public class LineAnalysisTreeDTO { public static class EquipmentNode { private Long id; // 设备ID private String name; // 设备名称 - private List parameters = new ArrayList<>(); + private List parameters; } // 参数节点 diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/ParameterInfoDTO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/ParameterInfoDTO.java new file mode 100644 index 0000000000..b7687b40f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/organization/vo/ParameterInfoDTO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.controller.admin.organization.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ParameterInfoDTO { + /** + * 参数ID + */ + private Long parameterId; + + /** + * 参数名称 + */ + private String parameterName; + + /** + * 参数代码 + */ + private String parameterCode; + + /** + * 参数类型 + */ + private String parameterType; + + /** + * 数据类型 + */ + private String dataType; + + /** + * 单位 + */ + private String unit; + + /** + * 系数 + */ + private Double ratio; +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/taskmanagement/vo/TaskManagementSaveReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/taskmanagement/vo/TaskManagementSaveReqVO.java index 2f977cae03..5690472bf2 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/taskmanagement/vo/TaskManagementSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/taskmanagement/vo/TaskManagementSaveReqVO.java @@ -27,9 +27,11 @@ public class TaskManagementSaveReqVO { private Integer taskType; @Schema(description = "设备列表") + @NotEmpty(message = "名称不能为空") private String deviceList; @Schema(description = "项目表单") + @NotNull private Long projectForm; @Schema(description = "起止开始日期") diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/vo/TicketManagementBatchUpdateReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/vo/TicketManagementBatchUpdateReqVO.java index f3539708bd..55f3f7e897 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/vo/TicketManagementBatchUpdateReqVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/vo/TicketManagementBatchUpdateReqVO.java @@ -16,5 +16,5 @@ public class TicketManagementBatchUpdateReqVO { @Schema(description = "作业状态", example = "2") @NotNull(message = "作业状态不能为空") - private Integer jobStatus ; // 默认值为2 + private Integer jobStatus ; } \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceService.java index ecb6dc0ae8..e916916b56 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.service.energydevice; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDeviceConsumptionReqVO; import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDevicePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDeviceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDeviceSaveReqVO; @@ -109,7 +110,7 @@ public interface EnergyDeviceService { return convertMap(getList(ids), EnergyDeviceDO::getId); } - List queryDataRecords(String startTime,String endTime); + List queryDataRecords(EnergyDeviceConsumptionReqVO deviceConsumptionReqVO); } \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImpl.java index 89a0e597ef..79734439a4 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImpl.java @@ -4,19 +4,21 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.iot.dal.devicecontactmodel.DeviceContactModelDO; +import cn.iocoder.yudao.module.iot.dal.mysql.devicecontactmodel.DeviceContactModelMapper; import cn.iocoder.yudao.module.iot.service.device.TDengineService; -import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDevicePageReqVO; -import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDeviceRespVO; -import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.EnergyDeviceSaveReqVO; -import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.OperationRulesVO; +import cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo.*; import cn.iocoder.yudao.module.mes.dal.dataobject.energydevice.EnergyDeviceCheckRecordDO; import cn.iocoder.yudao.module.mes.dal.dataobject.energydevice.EnergyDeviceDO; import cn.iocoder.yudao.module.mes.dal.mysql.energydevice.EnergyDeviceCheckRecordMapper; import cn.iocoder.yudao.module.mes.dal.mysql.energydevice.EnergyDeviceMapper; import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,6 +26,8 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.text.DecimalFormat; import java.time.LocalDateTime; import java.util.*; @@ -39,6 +43,7 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; */ @Service @Validated +@Slf4j public class EnergyDeviceServiceImpl implements EnergyDeviceService { @Resource @@ -49,6 +54,8 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService { private MesNoRedisDAO noRedisDAO; @Resource private TDengineService tDengineService; + @Resource + private DeviceContactModelMapper deviceContactModelMapper; @Override public Long createEnergyDevice(EnergyDeviceSaveReqVO createReqVO) { @@ -242,50 +249,647 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService { } @Override - public List queryDataRecords(String startTime,String endTime) { - List energyDeviceRespVOArrayList = new ArrayList<>(); - List energyDeviceDO = energyDeviceMapper.selectList(); - if (energyDeviceDO.isEmpty()){ + public List queryDataRecords(EnergyDeviceConsumptionReqVO deviceConsumptionReqVO) { + List result = new ArrayList<>(); + List energyDeviceDO = energyDeviceMapper.selectList( + Wrappers.lambdaQuery() + .like(StringUtils.isNotBlank(deviceConsumptionReqVO.getName()), EnergyDeviceDO::getName, deviceConsumptionReqVO.getName()) + .eq(deviceConsumptionReqVO.getOrgId() != null, EnergyDeviceDO::getOrgId, deviceConsumptionReqVO.getOrgId())); + + if (energyDeviceDO == null || energyDeviceDO.isEmpty()) { throw exception(ENERGY_LIST_NOT_EXISTS); } + for (EnergyDeviceDO deviceDO : energyDeviceDO) { - EnergyDeviceRespVO energyDeviceRespVO = new EnergyDeviceRespVO(); - if (StringUtils.isBlank(deviceDO.getRules())){ + if (StringUtils.isBlank(deviceDO.getRules())) { continue; } - - //查询每个点位的Id + // 解析规则 List operationRulesVOList = JSON.parseArray(deviceDO.getRules(), OperationRulesVO.class); - Map> operationRulesVOMap =new HashMap<>(); - - for (OperationRulesVO operationRulesVO : operationRulesVOList) { - List operationRulesVOS = new ArrayList<>(); - //获取Td列表 - List> maps = tDengineService.getstDeviceDataOrderByTimeDesc(operationRulesVO.getDeviceId(), startTime, endTime); - for (Map map : maps) { - String queryData = map.get("queryData").toString(); - - //获取json数据列表 - List deviceContactModelDOS = JSON.parseArray(queryData, DeviceContactModelDO.class); - for (DeviceContactModelDO deviceContactModelDO : deviceContactModelDOS) { - if (operationRulesVO.equals(deviceContactModelDO.getId())){ - OperationRulesVO operationRulesVO1 = new OperationRulesVO(); - operationRulesVO1.setPointId(deviceContactModelDO.getId()); - operationRulesVO1.setPointValue((String) deviceContactModelDO.getAddressValue()); - operationRulesVOS.add(operationRulesVO1); + if (operationRulesVOList == null || operationRulesVOList.isEmpty()) { + continue; + } + + try { + // 计算设备结果 + EnergyDeviceRespVO deviceRespVO = buildEnergyDeviceRespVO(deviceDO, operationRulesVOList, deviceConsumptionReqVO.getStartTime(), deviceConsumptionReqVO.getEndTime()); + if (deviceRespVO != null) { + result.add(deviceRespVO); + } + } catch (Exception e) { + log.error("计算设备结果失败, deviceId: {}", deviceDO.getId(), e); + } + } + + return result; + } + + /** + * 构建EnergyDeviceRespVO对象 + */ + private EnergyDeviceRespVO buildEnergyDeviceRespVO(EnergyDeviceDO deviceDO, + List rules, + String startTime, String endTime) { + if (deviceDO == null || rules == null || rules.isEmpty()) { + return null; + } + + EnergyDeviceRespVO respVO = new EnergyDeviceRespVO(); + + // 设置设备基本信息 + respVO.setId(deviceDO.getId()); + respVO.setName(deviceDO.getName()); + respVO.setCode(deviceDO.getCode()); + respVO.setInfo(deviceDO.getInfo()); + respVO.setCheckCron(deviceDO.getCheckCron()); + respVO.setLastCheckTime(deviceDO.getLastCheckTime()); + respVO.setLastCheckValue(deviceDO.getLastCheckValue()); + respVO.setUnitName(deviceDO.getUnitName()); + respVO.setIsEnable(deviceDO.getIsEnable()); + respVO.setCreateTime(deviceDO.getCreateTime()); + respVO.setUpdateTime(deviceDO.getUpdateTime()); + respVO.setDeviceTypeId(deviceDO.getDeviceTypeId()); + respVO.setDeviceTypeName(deviceDO.getDeviceTypeName()); + respVO.setOrgId(deviceDO.getOrgId()); + respVO.setOrgName(deviceDO.getOrgName()); + respVO.setRules(deviceDO.getRules()); + respVO.setOperationRulesVOList(rules); + + // 计算数据结果 + Map calculationResult = calculateDeviceData(deviceDO, rules, startTime, endTime); + if (calculationResult == null) { + return respVO; + } + + // 设置能耗总用量差值 + Double totalDifference = (Double) calculationResult.get("totalDifference"); + if (totalDifference != null) { + respVO.setEnergyConsumption(formatDouble(totalDifference)); + } else { + respVO.setEnergyConsumption("0.0"); + } + + // 设置每个点位参数的差值,key为点位参数名称 + Map operationRulesVOMap = buildPointDifferenceMap(calculationResult, deviceDO, rules); + respVO.setOperationRulesVOMap(operationRulesVOMap); + + return respVO; + } + + + /** + * 从查询结果中提取特定点位的数据 + */ + private Map getPointData(Map dataMap, Long pointId) { + if (dataMap == null || pointId == null) { + return null; + } + + try { + Object queryDataObj = dataMap.get("queryData"); + if (queryDataObj == null) { + return null; + } + + String queryData = queryDataObj.toString(); + if (StringUtils.isBlank(queryData)) { + return null; + } + + // 处理编码问题 + queryData = fixEncoding(queryData); + + // 解析JSON数组 + JSONArray jsonArray = JSON.parseArray(queryData); + + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObj = jsonArray.getJSONObject(i); + + // 安全获取id + Long dataPointId = null; + try { + dataPointId = jsonObj.getLong("id"); + } catch (Exception e) { + continue; + } + + if (dataPointId == null) { + continue; + } + + // 匹配点位ID + if (pointId.equals(dataPointId)) { + Map pointData = new HashMap<>(); + + // 提取所有需要的字段 + pointData.put("id", dataPointId); + + // 安全获取字段 + pointData.put("address", getJsonString(jsonObj, "address")); + + // 处理值 + Object value = jsonObj.get("addressValue"); + Double doubleValue = null; + if (value != null) { + try { + if (value instanceof Number) { + doubleValue = ((Number) value).doubleValue(); + } else { + doubleValue = Double.parseDouble(value.toString()); + } + } catch (NumberFormatException e) { + log.warn("点位值无法转换为数字: pointId={}, value={}", pointId, value); + doubleValue = null; } } + pointData.put("value", doubleValue); + pointData.put("addressValue", value); + + pointData.put("attributeCode", getJsonString(jsonObj, "attributeCode")); + pointData.put("attributeName", getJsonString(jsonObj, "attributeName")); + pointData.put("attributeType", getJsonString(jsonObj, "attributeType")); + pointData.put("dataType", getJsonString(jsonObj, "dataType")); + pointData.put("dataUnit", getJsonString(jsonObj, "dataUnit")); + + // 安全获取ratio + try { + Float ratio = jsonObj.getFloat("ratio"); + pointData.put("ratio", ratio); + } catch (Exception e) { + pointData.put("ratio", null); + } + + return pointData; + } + } + + } catch (Exception e) { + log.error("解析点位数据失败, pointId: {}", pointId, e); + } + + return null; + } + + /** + * 从JSON对象安全获取字符串 + */ + private String getJsonString(JSONObject jsonObj, String key) { + try { + return jsonObj.getString(key); + } catch (Exception e) { + return ""; + } + } + + /** + * 格式化double值为字符串 + */ + private String formatDouble(Double value) { + if (value == null) { + return "0.0"; + } + + DecimalFormat df = new DecimalFormat("#.##"); + return df.format(value); + } + /** + * 计算设备数据 + */ + private Map calculateDeviceData(EnergyDeviceDO deviceDO, + List rules, + String startTime, String endTime) { + if (deviceDO == null || rules == null || rules.isEmpty()) { + return null; + } + + Map result = new HashMap<>(); + + try { + // 分别计算最新和最晚时间的数据 + Map latestData = getTimePointData(rules, startTime, endTime, true); + Map earliestData = getTimePointData(rules, startTime, endTime, false); + + if (latestData == null || earliestData == null) { + return result; + } + + // 使用相同的规则计算两个时间点的总值 + Double latestTotal = calculateTotalByRules(latestData, rules); + Double earliestTotal = calculateTotalByRules(earliestData, rules); + + // 计算每个点位的差值 + List> pointDifferences = calculatePointDifferences(latestData, earliestData, rules); + + result.put("latestData", latestData); + result.put("earliestData", earliestData); + result.put("latestTotal", latestTotal != null ? latestTotal : 0.0); + result.put("earliestTotal", earliestTotal != null ? earliestTotal : 0.0); + result.put("totalDifference", (latestTotal != null && earliestTotal != null) ? + latestTotal - earliestTotal : 0.0); + result.put("pointDifferences", pointDifferences != null ? pointDifferences : Collections.emptyList()); + + } catch (Exception e) { + log.error("计算设备数据失败, deviceId: {}", deviceDO.getId(), e); + } + + return result; + } + + /** + * 从设备数据中获取点位值 + */ + private Double getPointValueFromDataByDevice(Map timePointData, Long deviceId, Long pointId) { + if (timePointData == null || deviceId == null || pointId == null) { + return null; + } + + String deviceKey = "device_" + deviceId; + Map deviceData = (Map) timePointData.get(deviceKey); + if (deviceData == null) { + return null; + } + + return getPointValueFromData(deviceData, pointId); + } + + /** + * 获取点位值 + */ + private Double getPointValueFromData(Map dataMap, Long pointId) { + if (dataMap == null || pointId == null) { + return null; + } + + Map pointData = getPointData(dataMap, pointId); + if (pointData != null) { + Object value = pointData.get("value"); + if (value instanceof Double) { + return (Double) value; + } else if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + } + return null; + } + + /** + * 获取指定时间点的数据 + */ + private Map getTimePointData(List rules, + String startTime, String endTime, + boolean isLatest) { + if (rules == null || rules.isEmpty()) { + return null; + } + + Map timePointData = new HashMap<>(); + String timestamp = null; + + for (OperationRulesVO rule : rules) { + if (rule == null || rule.getDeviceId() == null) { + continue; + } + + List> maps = null; + try { + maps = tDengineService.getstDeviceDataOrderByTimeDesc( + rule.getDeviceId(), startTime, endTime); + } catch (Exception e) { + log.error("查询设备数据失败, deviceId: {}", rule.getDeviceId(), e); + continue; + } + + if (maps == null || maps.isEmpty()) { + continue; + } + + Map dataMap = null; + try { + if (isLatest) { + dataMap = maps.get(0); + } else { + dataMap = maps.get(maps.size() - 1); + } + } catch (Exception e) { + log.error("获取时间点数据失败, deviceId: {}, isLatest: {}", rule.getDeviceId(), isLatest, e); + continue; + } + + if (dataMap == null) { + continue; + } + + if (timestamp == null && dataMap.containsKey("timestamp")) { + Object tsObj = dataMap.get("timestamp"); + if (tsObj != null) { + timestamp = tsObj.toString(); } - operationRulesVOMap.put(operationRulesVO.getPointId(),operationRulesVOS); + } + String deviceKey = "device_" + rule.getDeviceId(); + if (!timePointData.containsKey(deviceKey)) { + timePointData.put(deviceKey, dataMap); } - energyDeviceRespVO.setOperationRulesVOMap(operationRulesVOMap); - energyDeviceRespVOArrayList.add(energyDeviceRespVO); } + if (timestamp != null) { + timePointData.put("timestamp", timestamp); + } else { + timePointData.put("timestamp", ""); + } + + return timePointData.isEmpty() ? null : timePointData; + } + + /** + * 根据规则计算总值 + */ + private Double calculateTotalByRules(Map timePointData, List rules) { + if (timePointData == null || timePointData.isEmpty() || rules == null || rules.isEmpty()) { + return 0.0; + } + + Double total = null; + String lastOperator = null; + + for (int i = 0; i < rules.size(); i++) { + OperationRulesVO rule = rules.get(i); + if (rule == null || rule.getDeviceId() == null || rule.getPointId() == null) { + continue; + } + + String deviceKey = "device_" + rule.getDeviceId(); + Map deviceData = (Map) timePointData.get(deviceKey); + if (deviceData == null) { + continue; + } + + Double pointValue = getPointValueFromData(deviceData, rule.getPointId()); + if (pointValue == null) { + continue; + } + + if (total == null) { + total = pointValue; + } else { + String operator = null; + if (rule.getOperator() != null) { + operator = rule.getOperator().trim(); + } + + if (StringUtils.isEmpty(operator)) { + operator = lastOperator; + } + + if (StringUtils.isNotEmpty(operator)) { + try { + total = applyOperator(total, pointValue, operator); + } catch (Exception e) { + log.error("应用运算符失败: current={}, value={}, operator={}", total, pointValue, operator, e); + total += pointValue; + } + } else { + total += pointValue; + } + } + + lastOperator = rule.getOperator(); + } + + return total != null ? total : 0.0; + } + + /** + * 计算每个点位的差值 + */ + private List> calculatePointDifferences(Map latestData, + Map earliestData, + List rules) { + List> differences = new ArrayList<>(); + + if (rules == null || rules.isEmpty()) { + return differences; + } + + for (OperationRulesVO rule : rules) { + if (rule == null || rule.getDeviceId() == null || rule.getPointId() == null) { + continue; + } + + Map pointDiff = new HashMap<>(); + pointDiff.put("pointId", rule.getPointId()); + pointDiff.put("operator", rule.getOperator() != null ? rule.getOperator() : ""); + pointDiff.put("deviceId", rule.getDeviceId()); + + Double latestValue = getPointValueFromDataByDevice(latestData, rule.getDeviceId(), rule.getPointId()); + Double earliestValue = getPointValueFromDataByDevice(earliestData, rule.getDeviceId(), rule.getPointId()); + + pointDiff.put("latestValue", latestValue != null ? latestValue : 0.0); + pointDiff.put("earliestValue", earliestValue != null ? earliestValue : 0.0); + + if (latestValue != null && earliestValue != null) { + Double difference = latestValue - earliestValue; + pointDiff.put("difference", difference); + } else if (latestValue != null) { + pointDiff.put("difference", latestValue); + } else if (earliestValue != null) { + pointDiff.put("difference", -earliestValue); + } else { + pointDiff.put("difference", 0.0); + } + + differences.add(pointDiff); + } + + return differences; + } + + /** + * 应用运算符计算 + */ + private Double applyOperator(Double current, Double value, String operator) { + if (current == null || value == null || operator == null) { + return current; + } + + String op = operator.trim(); + switch (op) { + case "+": + return current + value; + case "-": + return current - value; + case "*": + return current * value; + case "/": + if (Math.abs(value) > 0.000001) { // 避免除零 + return current / value; + } else { + log.warn("除数不能为0: current={}, value={}", current, value); + return current; + } + default: + log.warn("不支持的操作符: {}, 使用加法", operator); + return current + value; + } + } + + /** + * 修复编码问题 + */ + private String fixEncoding(String str) { + if (StringUtils.isBlank(str)) { + return str; + } + + try { + // 尝试UTF-8解码 + byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1); + return new String(bytes, StandardCharsets.UTF_8); + } catch (Exception e) { + return str; + } + } + + + /** + * 优化:批量构建点位差值Map + */ + private Map buildPointDifferenceMap(Map calculationResult, + EnergyDeviceDO deviceDO, + List originalRules) { + Map result = new HashMap<>(); + + if (calculationResult == null || originalRules == null || originalRules.isEmpty()) { + return result; + } + + List> pointDifferences = (List>) calculationResult.get("pointDifferences"); + if (pointDifferences == null || pointDifferences.isEmpty()) { + return result; + } + + // 获取最新数据用于获取点位名称 + Map latestData = (Map) calculationResult.get("latestData"); + + // 收集所有点位ID + List allPointIds = new ArrayList<>(); + for (Map pointDiff : pointDifferences) { + Long pointId = (Long) pointDiff.get("pointId"); + if (pointId != null) { + allPointIds.add(pointId); + } + } + + // 批量从本地数据库获取点位名称 + Map pointNameMap = batchGetPointNamesFromLocalDB(allPointIds); + + for (Map pointDiff : pointDifferences) { + Long pointId = (Long) pointDiff.get("pointId"); + if (pointId == null) { + continue; + } + + // 获取点位名称 + String pointName = null; + + // 1. 尝试从TD数据库获取 + pointName = getPointNameFromTDData(latestData, pointId, pointDiff); + + // 2. 如果TD数据库没有,从本地数据库获取 + if (StringUtils.isBlank(pointName)) { + pointName = pointNameMap.get(pointId); + } + + // 获取差值 + Double difference = (Double) pointDiff.get("difference"); + String differenceStr = formatDouble(difference != null ? difference : 0.0); + + // 以点位名称为key,差值为value + if (StringUtils.isNotBlank(pointName)) { + result.put(pointName, differenceStr); + } else { + // 如果还没有点位名称,使用点位ID作为key + result.put("点位" + pointId, differenceStr); + } + } + + return result; + } + + /** + * 从TD数据库数据中获取点位名称 + */ + private String getPointNameFromTDData(Map timePointData, Long pointId, Map pointDiff) { + if (timePointData == null || pointId == null || pointDiff == null) { + return null; + } + + Long deviceId = (Long) pointDiff.get("deviceId"); + if (deviceId == null) { + return null; + } + + String deviceKey = "device_" + deviceId; + Map deviceData = (Map) timePointData.get(deviceKey); + if (deviceData == null) { + return null; + } + + Map pointData = getPointData(deviceData, pointId); + if (pointData == null) { + return null; + } + + String attributeName = (String) pointData.get("attributeName"); + if (StringUtils.isNotBlank(attributeName)) { + return attributeName; + } + + String attributeCode = (String) pointData.get("attributeCode"); + if (StringUtils.isNotBlank(attributeCode)) { + return attributeCode; + } + + return null; + } + + /** + * 批量获取点位名称(优化性能) + */ + private Map batchGetPointNamesFromLocalDB(List pointIds) { + Map result = new HashMap<>(); + + if (pointIds == null || pointIds.isEmpty()) { + return result; + } + + try { + // 批量查询点位信息 + List deviceContacts = deviceContactModelMapper.selectBatchIds(pointIds); + if (deviceContacts != null && !deviceContacts.isEmpty()) { + for (DeviceContactModelDO deviceContact : deviceContacts) { + if (deviceContact == null || deviceContact.getId() == null) { + continue; + } + + String pointName = null; + if (StringUtils.isNotBlank(deviceContact.getAttributeName())) { + pointName = deviceContact.getAttributeName(); + } else if (StringUtils.isNotBlank(deviceContact.getAttributeCode())) { + pointName = deviceContact.getAttributeCode(); + } + + if (StringUtils.isNotBlank(pointName)) { + result.put(deviceContact.getId(), pointName); + } + } + } + } catch (Exception e) { + log.error("批量查询点位信息失败, pointIds: {}", pointIds, e); + } - return energyDeviceRespVOArrayList; + return result; } } \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/organization/OrganizationService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/organization/OrganizationService.java index 26d3fa7f00..db9d11463d 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/organization/OrganizationService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/organization/OrganizationService.java @@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.mes.service.organization; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.mes.controller.admin.organization.vo.LineAnalysisTreeDTO; -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.dal.dataobject.organization.OrganizationDO; import javax.validation.Valid; @@ -80,5 +77,7 @@ public interface OrganizationService { return convertMap(getOrganizationVOList(ids), OrganizationDO::getId); } - List deviceParameterAnalysis(String keyword); + List deviceParameterAnalysis(String keyword,Integer showDevices); + +// List getDeviceParametersByOrganizationId(Long id); } \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/organization/OrganizationServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/organization/OrganizationServiceImpl.java index 35fcb0124a..fbbab65da2 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/organization/OrganizationServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/organization/OrganizationServiceImpl.java @@ -257,374 +257,405 @@ public class OrganizationServiceImpl implements OrganizationService { } @Override - public List deviceParameterAnalysis(String keyword) { + public List deviceParameterAnalysis(String keyword, Integer showDevices) { + // 参数验证 + if (showDevices == null || (showDevices != 1 && showDevices != 2)) { + showDevices = 1; // 默认展示设备和参数 + } + + boolean needShowDevices = showDevices == 1; // 1-展示,2-不展示 - //1. 获取产线集合 + // 1. 获取产线集合 OrganizationListReqVO organizationListReqVO = new OrganizationListReqVO(); List organizationDOS = getOrganizationList(organizationListReqVO); List organizationRespVOS = buildVOList(organizationDOS); if (organizationRespVOS.isEmpty()) { - return Collections.emptyList(); + return Collections.emptyList(); } - // 2. 获取所有有machineId的产线 - List machineIds = organizationRespVOS.stream() + // 2. 获取所有有machineId的组织 + List deviceIds = organizationRespVOS.stream() .map(OrganizationRespVO::getMachineId) .filter(Objects::nonNull) + .distinct() .collect(Collectors.toList()); - // 3. 根据machineId查询设备 - List allDevices = Collections.emptyList(); - if (!machineIds.isEmpty()) { + // 3. 查询设备信息 + Map deviceMap; + if (!deviceIds.isEmpty()) { LambdaQueryWrapper deviceWrapper = new LambdaQueryWrapper<>(); - deviceWrapper.in(DeviceDO::getId, machineIds) + deviceWrapper.in(DeviceDO::getId, deviceIds) .eq(DeviceDO::getIsEnable, true); - allDevices = deviceMapper.selectList(deviceWrapper); + List devices = deviceMapper.selectList(deviceWrapper); + deviceMap = devices.stream() + .collect(Collectors.toMap(DeviceDO::getId, Function.identity())); + } else { + deviceMap = new HashMap<>(); } - // 4. 获取所有参数 - List allParameters = getAllParameters(allDevices); - - - // 5. 构建映射关系 - Map deviceById = allDevices.stream() - .collect(Collectors.toMap(DeviceDO::getId, Function.identity())); + // 4. 查询设备参数 + Map> paramsByDeviceId; + if (!deviceIds.isEmpty()) { + LambdaQueryWrapper paramWrapper = new LambdaQueryWrapper<>(); + paramWrapper.in(DeviceContactModelDO::getDeviceId, deviceIds) + .orderByAsc(DeviceContactModelDO::getSort); + List allParameters = deviceContactModelMapper.selectList(paramWrapper); + + paramsByDeviceId = allParameters.stream() + .filter(param -> param.getDeviceId() != null) + .collect(Collectors.groupingBy(DeviceContactModelDO::getDeviceId)); + } else { + paramsByDeviceId = new HashMap<>(); + } - // 6. 构建设备按产线分组的映射 - Map> 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); - } + // 5. 构建产线ID到orgClass的映射 + Map lineOrgClassMap = new HashMap<>(); + for (int i = 0; i < organizationDOS.size(); i++) { + OrganizationDO orgDO = organizationDOS.get(i); + OrganizationRespVO orgVO = organizationRespVOS.get(i); + if (orgDO.getOrgClass() != null && orgVO != null) { + lineOrgClassMap.put(orgVO.getId(), orgDO.getOrgClass()); } } - Map> paramsByDeviceId = allParameters.stream() - .filter(param -> param.getDeviceId() != null) - .collect(Collectors.groupingBy(DeviceContactModelDO::getDeviceId)); - - - - // 获取产线与父节点的映射关系 - Map lineParentIdMap = organizationRespVOS.stream() - .collect(Collectors.toMap( - OrganizationRespVO::getId, - line -> line.getParentId() != null ? line.getParentId() : 0L, // 如果父节点为空,使用默认值0 - (existing, replacement) -> existing - )); - // 构建产线ID到产线对象的映射 - Map lineMap = organizationRespVOS.stream() - .collect(Collectors.toMap(OrganizationRespVO::getId, Function.identity())); - - // 获取所有匹配的产线(包括下级匹配的) - List matchedLines = getMatchedLinesWithAncestors( - organizationRespVOS, keyword, allDevices, paramsByDeviceId, lineParentIdMap, lineMap - ); - - - // 7. 构建树结构 - return buildTreeStructureWithKeyword(matchedLines, devicesByLineId, paramsByDeviceId,keyword,lineParentIdMap); - - } - - private List getMatchedLinesWithAncestors( - List allLines, - String keyword, - List allDevices, - Map> paramsByDeviceId, - Map lineParentIdMap, - Map lineMap) { + // 6. 构建组织ID到子节点的映射 + Map> childrenByParentId = organizationRespVOS.stream() + .filter(org -> org.getParentId() != null && org.getParentId() != 0L) + .collect(Collectors.groupingBy(OrganizationRespVO::getParentId)); + // 7. 如果有搜索关键词,筛选匹配的节点 + Set matchedNodeIds = new HashSet<>(); boolean hasKeyword = StringUtils.isNotBlank(keyword); - String lowerKeyword = hasKeyword ? keyword.toLowerCase() : ""; - // 存储最终要包含的产线ID - Set lineIdsToInclude = new HashSet<>(); + if (hasKeyword) { + String lowerKeyword = keyword.toLowerCase(); - // 1. 首先找出直接匹配的产线 - for (OrganizationRespVO line : allLines) { - boolean lineMatch = !hasKeyword || - (line.getName() != null && line.getName().toLowerCase().contains(lowerKeyword)); + // 查找组织名称匹配的节点 + for (OrganizationRespVO node : organizationRespVOS) { + boolean nodeMatched = false; - if (lineMatch) { - // 添加到结果集 - lineIdsToInclude.add(line.getId()); - // 向上查找所有父级节点 - addAllAncestors(line.getId(), lineParentIdMap, lineMap, lineIdsToInclude); - } - } + // 1. 检查组织名称是否匹配 + if (node.getName() != null && node.getName().toLowerCase().contains(lowerKeyword)) { + nodeMatched = true; + } - // 2. 查找设备匹配的产线 - if (hasKeyword) { - for (DeviceDO device : allDevices) { - boolean deviceMatch = device.getDeviceName() != null && - device.getDeviceName().toLowerCase().contains(lowerKeyword); - - if (deviceMatch) { - // 找到这个设备所属的产线 - for (OrganizationRespVO line : allLines) { - if (line.getMachineId() != null && line.getMachineId().equals(device.getId())) { - lineIdsToInclude.add(line.getId()); - addAllAncestors(line.getId(), lineParentIdMap, lineMap, lineIdsToInclude); + // 2. 如果没有组织名称匹配,检查该节点是否有设备匹配 + if (!nodeMatched && needShowDevices && node.getMachineId() != null) { + DeviceDO device = deviceMap.get(node.getMachineId()); + if (device != null) { + // 检查设备名称是否匹配 + if (device.getDeviceName() != null && + device.getDeviceName().toLowerCase().contains(lowerKeyword)) { + nodeMatched = true; } - } - } - } - } - // 3. 查找参数匹配的产线 - if (hasKeyword) { - for (Map.Entry> entry : paramsByDeviceId.entrySet()) { - Long deviceId = entry.getKey(); - List params = entry.getValue(); - - boolean hasMatchingParam = params.stream() - .anyMatch(param -> param.getAttributeName() != null && - param.getAttributeName().toLowerCase().contains(lowerKeyword)); - - if (hasMatchingParam) { - // 找到这个设备所属的产线 - for (OrganizationRespVO line : allLines) { - if (line.getMachineId() != null && line.getMachineId().equals(deviceId)) { - lineIdsToInclude.add(line.getId()); - addAllAncestors(line.getId(), lineParentIdMap, lineMap, lineIdsToInclude); + // 检查设备参数是否匹配 + if (!nodeMatched) { + List deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>()); + boolean hasMatchingParam = deviceParams.stream() + .anyMatch(param -> param.getAttributeName() != null && + param.getAttributeName().toLowerCase().contains(lowerKeyword)); + if (hasMatchingParam) { + nodeMatched = true; + } } } } + + if (nodeMatched) { + // 将当前节点加入匹配列表 + matchedNodeIds.add(node.getId()); + // 迭代添加所有子节点 + addAllDescendants(node.getId(), childrenByParentId, matchedNodeIds); + } } - } - // 如果没有关键词,返回所有产线 - if (!hasKeyword) { - return allLines; + // 如果没有匹配任何节点,返回空列表 + if (matchedNodeIds.isEmpty()) { + return Collections.emptyList(); + } + } else { + // 无关键词时,包含所有节点 + matchedNodeIds.addAll(organizationRespVOS.stream() + .map(OrganizationRespVO::getId) + .collect(Collectors.toSet())); } - // 只返回需要包含的产线 - return allLines.stream() - .filter(line -> lineIdsToInclude.contains(line.getId())) - .collect(Collectors.toList()); - } - - private void addAllAncestors(Long lineId, - Map lineParentIdMap, - Map lineMap, - Set lineIdsToInclude) { - Long currentParentId = lineParentIdMap.get(lineId); - - // 递归向上查找所有父级节点 - while (currentParentId != null && currentParentId != 0L) { - lineIdsToInclude.add(currentParentId); + // 8. 找到最顶层的匹配节点(没有匹配的父节点) + Set topLevelNodeIds = new HashSet<>(matchedNodeIds); - // 继续向上查找 - currentParentId = lineParentIdMap.get(currentParentId); + // 从匹配节点中移除那些父节点也在匹配列表中的节点 + for (OrganizationRespVO node : organizationRespVOS) { + if (matchedNodeIds.contains(node.getId()) && node.getParentId() != null && + node.getParentId() != 0L && matchedNodeIds.contains(node.getParentId())) { + topLevelNodeIds.remove(node.getId()); + } } - } - private List buildTreeStructureWithKeyword(List lines, - Map> devicesByLineId, - Map> paramsByDeviceId, - String keyword, - Map lineParentIdMap) { + // 9. 获取顶层节点 + Map nodeMap = organizationRespVOS.stream() + .collect(Collectors.toMap(OrganizationRespVO::getId, Function.identity())); - // 统一处理关键词 - boolean hasKeyword = StringUtils.isNotBlank(keyword); - String lowerKeyword = hasKeyword ? keyword.toLowerCase() : ""; + List topLevelNodes = topLevelNodeIds.stream() + .map(nodeMap::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); - // 如果lines已经过滤过,这里不再需要复杂的匹配判断 - if (!hasKeyword) { - // 没有关键词时,返回完整的树结构 - return lines.stream().map(line -> { - Long parentId = lineParentIdMap.getOrDefault(line.getId(), 0L); + // 10. 构建树结构 + return buildOrganizationTreeWithChildren(topLevelNodes, matchedNodeIds, childrenByParentId, + deviceMap, paramsByDeviceId, lineOrgClassMap, keyword, organizationRespVOS, needShowDevices, hasKeyword); + } - // 获取该产线的设备 - List lineDevices = devicesByLineId.getOrDefault(line.getId(), new ArrayList<>()); + /** + * 迭代添加所有子孙节点 + */ + private void addAllDescendants(Long nodeId, + Map> childrenByParentId, + Set matchedNodeIds) { + if (childrenByParentId == null || childrenByParentId.isEmpty()) { + return; + } - // 构建设备节点(显示所有设备和参数) - List equipmentNodes = lineDevices.stream() - .map(device -> { - List deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>()); + // 使用队列进行广度优先遍历 + Queue queue = new LinkedList<>(); + queue.offer(nodeId); - List parameterNodes = deviceParams.stream() - .map(this::buildParameterNode) - .collect(Collectors.toList()); + while (!queue.isEmpty()) { + Long currentId = queue.poll(); - return LineAnalysisTreeDTO.EquipmentNode.builder() - .id(device.getId()) - .name(device.getDeviceName()) - .parameters(parameterNodes) - .build(); - }) - .collect(Collectors.toList()); - - return LineAnalysisTreeDTO.LineNode.builder() - .id(line.getId()) - .name(line.getName()) - .parentId(parentId) - .equipments(equipmentNodes) - .build(); - }).collect(Collectors.toList()); - } - - // 有关键词时,lines已经包含了匹配的产线及其父级产线 - // 但我们仍然需要根据关键词过滤设备和参数 - - // 记录匹配情况 - Map lineMatchedMap = new HashMap<>(); - Map deviceMatchedMap = new HashMap<>(); - - // 第一遍:分析匹配情况 - for (OrganizationRespVO line : lines) { - // 产线是否匹配 - boolean lineMatch = line.getName() != null && - line.getName().toLowerCase().contains(lowerKeyword); - lineMatchedMap.put(line.getId(), lineMatch); - - // 检查该产线的设备 - List lineDevices = devicesByLineId.getOrDefault(line.getId(), new ArrayList<>()); - for (DeviceDO device : lineDevices) { - // 设备是否匹配 - boolean deviceMatch = device.getDeviceName() != null && - device.getDeviceName().toLowerCase().contains(lowerKeyword); - deviceMatchedMap.put(device.getId(), deviceMatch); + List children = childrenByParentId.get(currentId); + if (children != null && !children.isEmpty()) { + for (OrganizationRespVO child : children) { + matchedNodeIds.add(child.getId()); + queue.offer(child.getId()); + } } } + } - // 第二遍:构建树结构 - return lines.stream().map(line -> { - boolean lineMatch = lineMatchedMap.getOrDefault(line.getId(), false); - Long parentId = lineParentIdMap.getOrDefault(line.getId(), 0L); + /** + * 构建组织树(包含当前节点及其所有子节点) + */ + private List buildOrganizationTreeWithChildren( + List topLevelNodes, + Set matchedNodeIds, + Map> childrenByParentId, + Map deviceMap, + Map> paramsByDeviceId, + Map lineOrgClassMap, + String keyword, + List allOrganizationRespVOS, + boolean needShowDevices, + boolean hasKeyword) { - // 获取该产线的设备 - List lineDevices = devicesByLineId.getOrDefault(line.getId(), new ArrayList<>()); + // 创建节点映射 + Map nodeMap = new HashMap<>(); - // 构建设备节点 - List equipmentNodes = lineDevices.stream() - .map(device -> { - boolean deviceMatch = deviceMatchedMap.getOrDefault(device.getId(), false); - List deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>()); + // 创建所有组织节点的映射 + Map allNodesMap = allOrganizationRespVOS.stream() + .collect(Collectors.toMap(OrganizationRespVO::getId, Function.identity())); - // 如果产线匹配,显示该产线下的所有设备 - if (lineMatch) { - List parameterNodes = deviceParams.stream() - .map(this::buildParameterNode) - .collect(Collectors.toList()); + // 获取所有匹配节点的完整列表(包括所有子孙节点) + Set allMatchedAndDescendantIds = new HashSet<>(); + for (Long matchedId : matchedNodeIds) { + allMatchedAndDescendantIds.add(matchedId); + addAllDescendants(matchedId, childrenByParentId, allMatchedAndDescendantIds); + } - return LineAnalysisTreeDTO.EquipmentNode.builder() - .id(device.getId()) - .name(device.getDeviceName()) - .parameters(parameterNodes) - .build(); - } + // 构建所有匹配节点的树节点 + for (OrganizationRespVO node : allOrganizationRespVOS) { + if (!allMatchedAndDescendantIds.contains(node.getId())) { + continue; + } - // 如果设备匹配,显示该设备的所有参数 - if (deviceMatch) { - List parameterNodes = deviceParams.stream() - .map(this::buildParameterNode) - .collect(Collectors.toList()); - - return LineAnalysisTreeDTO.EquipmentNode.builder() - .id(device.getId()) - .name(device.getDeviceName()) - .parameters(parameterNodes) - .build(); - } + // 构建设备节点 + List equipmentNodes = new ArrayList<>(); + + if (needShowDevices) { + // 有搜索关键词时获取所有设备,无关键词时只获取当前节点的设备 + List deviceIds = hasKeyword ? + getAllDeviceIdsForNode(node.getId(), childrenByParentId, allNodesMap, allMatchedAndDescendantIds) : + getCurrentDeviceId(node, allNodesMap); + + for (Long deviceId : deviceIds) { + DeviceDO device = deviceMap.get(deviceId); + if (device != null) { + // 获取设备参数 + List deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>()); + + // 检查设备和参数是否匹配关键词 + boolean shouldIncludeDevice = false; + List filteredParams = new ArrayList<>(); + + if (hasKeyword) { + String lowerKeyword = keyword.toLowerCase(); + // 检查当前节点是否匹配关键词(组织名称匹配) + boolean isNodeNameMatched = node.getName() != null && + node.getName().toLowerCase().contains(lowerKeyword); + + if (!isNodeNameMatched) { + // 有关键词但不是组织名称匹配的情况 + boolean deviceNameMatches = device.getDeviceName() != null && + device.getDeviceName().toLowerCase().contains(lowerKeyword); + + // 检查参数是否匹配 + filteredParams = deviceParams.stream() + .filter(param -> param.getAttributeName() != null && + param.getAttributeName().toLowerCase().contains(lowerKeyword)) + .collect(Collectors.toList()); - // 检查是否有匹配的参数 - boolean hasMatchingParam = deviceParams.stream() - .anyMatch(param -> isParameterMatch(param, lowerKeyword)); + boolean hasMatchingParam = !filteredParams.isEmpty(); - if (!hasMatchingParam) { - return null; + // 如果设备名称或参数匹配,则包含设备 + if (deviceNameMatches || hasMatchingParam) { + shouldIncludeDevice = true; + // 如果设备名称匹配但参数不匹配,包含所有参数 + if (deviceNameMatches && filteredParams.isEmpty()) { + filteredParams = new ArrayList<>(deviceParams); + } } + } else { + // 是组织名称匹配的情况:包含所有设备和参数 + shouldIncludeDevice = true; + filteredParams = new ArrayList<>(deviceParams); + } + } else { + // 无关键词的情况:包含所有设备和参数 + shouldIncludeDevice = true; + filteredParams = new ArrayList<>(deviceParams); + } - // 只显示匹配的参数 - List parameterNodes = deviceParams.stream() - .filter(param -> isParameterMatch(param, lowerKeyword)) - .map(this::buildParameterNode) - .collect(Collectors.toList()); + if (shouldIncludeDevice) { + List paramInfos = filteredParams.stream() + .map(this::convertToSimpleInfo) + .collect(Collectors.toList()); - return LineAnalysisTreeDTO.EquipmentNode.builder() + // 检查设备是否已添加(避免重复) + boolean alreadyAdded = equipmentNodes.stream() + .anyMatch(e -> e.getId().equals(device.getId())); + + if (!alreadyAdded) { + equipmentNodes.add(LineAnalysisTreeDTO.EquipmentNode.builder() .id(device.getId()) .name(device.getDeviceName()) - .parameters(parameterNodes) - .build(); - }) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - return LineAnalysisTreeDTO.LineNode.builder() - .id(line.getId()) - .name(line.getName()) - .parentId(parentId) - .equipments(equipmentNodes) - .build(); - }) - .collect(Collectors.toList()); - } + .parameters(paramInfos) + .build()); + } + } + } + } + } -// /** -// * 检查产线下是否有匹配的设备或参数 -// */ -// private boolean checkIfLineHasMatchingDeviceOrParam(OrganizationRespVO line, -// Map> devicesByLineId, -// Map> paramsByDeviceId, -// String lowerKeyword, -// Map deviceMatchedMap) { -// -// List lineDevices = devicesByLineId.getOrDefault(line.getId(), new ArrayList<>()); -// -// for (DeviceDO device : lineDevices) { -// // 检查设备是否匹配 -// boolean deviceMatch = deviceMatchedMap.getOrDefault(device.getId(), false); -// if (deviceMatch) { -// return true; -// } -// -// // 检查设备下的参数是否匹配 -// List 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> paramsByDeviceId, -// String lowerKeyword) { -// -// List deviceParams = paramsByDeviceId.getOrDefault(device.getId(), new ArrayList<>()); -// return deviceParams.stream() -// .anyMatch(param -> isParameterMatch(param, lowerKeyword)); -// } + LineAnalysisTreeDTO.LineNode lineNode = LineAnalysisTreeDTO.LineNode.builder() + .id(node.getId()) + .name(node.getName()) + .orgClass(lineOrgClassMap.getOrDefault(node.getId(), null)) + .parentId(node.getParentId()) + .equipments(equipmentNodes) + .children(new ArrayList<>()) + .build(); + + nodeMap.put(node.getId(), lineNode); + } + + // 构建父子关系 + List result = new ArrayList<>(); + + for (LineAnalysisTreeDTO.LineNode lineNode : nodeMap.values()) { + if (lineNode.getParentId() == null || lineNode.getParentId() == 0L) { + // 根节点 + result.add(lineNode); + } else { + // 查找父节点 + LineAnalysisTreeDTO.LineNode parentNode = nodeMap.get(lineNode.getParentId()); + if (parentNode != null) { + parentNode.getChildren().add(lineNode); + } else { + // 父节点不在当前构建的节点中,但当前节点是匹配的 + // 这种情况下,当前节点应该作为根节点展示 + result.add(lineNode); + } + } + } + // 过滤:只保留顶层节点 + List filteredResult = new ArrayList<>(); + Set topLevelNodeIds = topLevelNodes.stream() + .map(OrganizationRespVO::getId) + .collect(Collectors.toSet()); + + for (LineAnalysisTreeDTO.LineNode node : result) { + if (topLevelNodeIds.contains(node.getId())) { + filteredResult.add(node); + } else if (node.getParentId() == null || node.getParentId() == 0L) { + // 或者是没有父节点的根节点 + filteredResult.add(node); + } + } + + return filteredResult; + } /** - * 判断参数是否匹配关键词 + * 获取当前节点自身的设备ID */ - private boolean isParameterMatch(DeviceContactModelDO param, String lowerKeyword) { - if (StringUtils.isBlank(lowerKeyword)) { - return true; + private List getCurrentDeviceId(OrganizationRespVO node, Map allNodesMap) { + List deviceIds = new ArrayList<>(); + + // 获取当前节点 + OrganizationRespVO currentNode = allNodesMap.get(node.getId()); + if (currentNode != null && currentNode.getMachineId() != null) { + deviceIds.add(currentNode.getMachineId()); } - return (param.getAttributeName() != null && param.getAttributeName().toLowerCase().contains(lowerKeyword)); + return deviceIds; } + /** + * 获取节点及其子孙节点的设备ID + */ + private List getAllDeviceIdsForNode(Long nodeId, + Map> childrenByParentId, + Map allNodesMap, + Set matchedNodeIds) { + Set deviceIds = new HashSet<>(); + + // 先检查当前节点是否有设备 + OrganizationRespVO currentNode = allNodesMap.get(nodeId); + if (currentNode != null && currentNode.getMachineId() != null) { + deviceIds.add(currentNode.getMachineId()); + } + + // 使用队列迭代获取所有子孙节点 + Queue queue = new LinkedList<>(); + queue.offer(nodeId); + + while (!queue.isEmpty()) { + Long currentId = queue.poll(); + + // 获取当前节点的子节点 + List children = childrenByParentId.get(currentId); + if (children != null) { + for (OrganizationRespVO child : children) { + if (matchedNodeIds.contains(child.getId())) { + // 如果子节点有设备,添加到设备列表 + if (child.getMachineId() != null) { + deviceIds.add(child.getMachineId()); + } + // 继续处理子节点的子节点 + queue.offer(child.getId()); + } + } + } + } + return new ArrayList<>(deviceIds); + } /** - * 构建参数节点 + * 将设备参数转换为简化的参数信息 */ - private LineAnalysisTreeDTO.ParameterNode buildParameterNode(DeviceContactModelDO param) { + private LineAnalysisTreeDTO.ParameterNode convertToSimpleInfo(DeviceContactModelDO param) { return LineAnalysisTreeDTO.ParameterNode.builder() .id(param.getId()) .name(param.getAttributeName()) @@ -636,29 +667,4 @@ public class OrganizationServiceImpl implements OrganizationService { .build(); } - - private List getAllParameters(List devices) { - - if (devices.isEmpty()) { - return Collections.emptyList(); - } - - List deviceIds = devices.stream() - .map(DeviceDO::getId) - .collect(Collectors.toList()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.in(DeviceContactModelDO::getDeviceId, deviceIds) - .orderByAsc(DeviceContactModelDO::getSort); // 按排序字段排序 - - List result = deviceContactModelMapper.selectList(wrapper); - - // 调试日志 - System.out.println("查询条件: 设备IDs=" + deviceIds); - System.out.println("查询结果数量: " + result.size()); - - return result; - } - - } \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/taskmanagement/TaskManagementServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/taskmanagement/TaskManagementServiceImpl.java index 996f2f5bd5..e966396c47 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/taskmanagement/TaskManagementServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/taskmanagement/TaskManagementServiceImpl.java @@ -109,7 +109,9 @@ public class TaskManagementServiceImpl implements TaskManagementService { PageResult taskManagementDOPageResult = taskManagementMapper.selectPage(pageReqVO); for (TaskManagementDO taskManagementDO : taskManagementDOPageResult.getList()) { PlanMaintenanceDO planMaintenanceDO = planMaintenanceMapper.selectById(taskManagementDO.getProjectForm()); - taskManagementDO.setProjectFormName(planMaintenanceDO.getPlanName()); + if (planMaintenanceDO !=null) { + taskManagementDO.setProjectFormName(planMaintenanceDO.getPlanName()); + } }