diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/PlanController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/PlanController.java index df488ee8a..eafe9b6b9 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/PlanController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/PlanController.java @@ -201,11 +201,9 @@ public class PlanController { return Collections.emptyList(); } - // 原有:投料管道名称 Map organizationMap = organizationService.getOrganizationVOMap( convertSet(list, PlanRespVO::getFeedingPipeline)); - // 新增:设备名称映射(按你项目里的设备 service 替换) Map deviceMap = deviceLedgerService.getDeviceMap( convertSet(list, PlanRespVO::getDeviceId)); @@ -213,19 +211,32 @@ public class PlanController { MapUtils.findAndThen(organizationMap, item.getFeedingPipeline(), organization -> item.setFeedingPipelineName(organization.getName())); - DeviceLedgerDO device = deviceMap.get(item.getDeviceId()); - if (device != null) { - item.setDeviceName(device.getDeviceName()); - } else { - String baseName = StringUtils.hasText(item.getDeviceName()) - ? item.getDeviceName() - : "设备[" + item.getDeviceId() + "]"; - item.setDeviceName(baseName + "(已删除)"); + if (item.getDeviceId() != null) { + DeviceLedgerDO device = deviceMap.get(item.getDeviceId()); + if (device != null) { + if (Boolean.TRUE.equals(device.getDeleted())) { + // 已删除:优先原值,其次 code-设备名,最后兜底“设备(已删除)” + String code = StringUtils.hasText(device.getDeviceCode()) ? device.getDeviceCode() : ""; + String name = StringUtils.hasText(device.getDeviceName()) ? device.getDeviceName() : ""; + String codeName = StringUtils.hasText(code) && StringUtils.hasText(name) + ? code + "-" + name + : code + name; + + String baseName = StringUtils.hasText(item.getDeviceName()) + ? item.getDeviceName() + : (StringUtils.hasText(codeName) ? codeName : "设备"); + + item.setDeviceName(baseName + "(已删除)"); + } else { + item.setDeviceName(device.getDeviceCode()+"-"+device.getDeviceName()); + } + } } }); } + @GetMapping("/export-excel") @Operation(summary = "导出生产计划 Excel") @PreAuthorize("@ss.hasPermission('mes:plan:export')") diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskDetailRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskDetailRespVO.java index 28a3df3ea..2b7fb5d5c 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskDetailRespVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskDetailRespVO.java @@ -108,4 +108,7 @@ public class TaskDetailRespVO { @Schema(description = "任务单编码", example = "") @ExcelProperty("任务单编码") private String taskCode; + + @Schema(description = "关联设备", example = "EQ-01-搅拌机,EQ-02-封口机") + private String deviceDisplayName; } \ 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/task/TaskServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java index 2f32ed247..8bb50d796 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java @@ -9,7 +9,9 @@ import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductRelationRespVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.productdevicerel.ProductDeviceRelDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.productdevicerel.ProductDeviceRelMapper; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; import cn.iocoder.yudao.module.mes.controller.admin.deviceledger.enums.CapacityTypeEnum; @@ -27,6 +29,7 @@ import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskDetailMapper; import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskMapper; import cn.iocoder.yudao.module.mes.dal.mysql.task.ViewTaskProductSummaryMapper; import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO; +import cn.iocoder.yudao.module.mes.service.deviceledger.DeviceLedgerService; import cn.iocoder.yudao.module.mes.strategy.task.ScheduleSortStrategyFactory; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -66,12 +69,19 @@ public class TaskServiceImpl implements TaskService { @Resource private MesNoRedisDAO noRedisDAO; + @Resource private ErpProductMapper erpProductMapper; + @Resource - @Lazy private DeviceLedgerMapper deviceLedgerMapper; + @Resource + private ProductDeviceRelMapper productDeviceRelMapper; + + @Resource + private DeviceLedgerService deviceLedgerService; + @Resource private AutoCodeUtil autoCodeUtil; @Resource @@ -251,28 +261,77 @@ public class TaskServiceImpl implements TaskService { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } - Map map = productService.getProductMap( - convertSet(list, TaskDetailDO::getProductId)); - Map unitMap = productUnitService.getProductUnitMap( - convertSet(list, TaskDetailDO::getUnitId)); - List resList = BeanUtils.toBean(list, TaskDetailRespVO.class, item -> { + Set productIds = convertSet(list, TaskDetailDO::getProductId); + Set unitIds = convertSet(list, TaskDetailDO::getUnitId); + + Map map = productService.getProductMap(productIds); + Map unitMap = productUnitService.getProductUnitMap(unitIds); + + // 1) 产品-设备关系(按 sort、id 排序,保证拼接顺序稳定) + List relList = productDeviceRelMapper.selectList( + Wrappers.lambdaQuery() + .in(ProductDeviceRelDO::getProductId, productIds) + .orderByAsc(ProductDeviceRelDO::getSort, ProductDeviceRelDO::getId)); + + // productId -> deviceId 列表(去重且保持顺序) + Map> productDeviceIdsMap = new HashMap<>(); + Set allDeviceIds = new HashSet<>(); + for (ProductDeviceRelDO rel : relList) { + productDeviceIdsMap + .computeIfAbsent(rel.getProductId(), k -> new LinkedHashSet<>()) + .add(rel.getDeviceId()); + allDeviceIds.add(rel.getDeviceId()); + } + + // 2) 批量查设备 + Map deviceMap = CollUtil.isEmpty(allDeviceIds) + ? Collections.emptyMap() + : deviceLedgerService.getDeviceMap(allDeviceIds); + + // 3) 先构建 productId -> "code-name,code-name" + Map productDeviceDisplayMap = new HashMap<>(); + for (Map.Entry> entry : productDeviceIdsMap.entrySet()) { + Long productId = entry.getKey(); + LinkedHashSet deviceIds = entry.getValue(); + + String deviceDisplay = deviceIds.stream() + .map(deviceMap::get) + .filter(Objects::nonNull) + .map(device -> { + String code = StringUtils.defaultString(device.getDeviceCode()); + String name = StringUtils.defaultString(device.getDeviceName()); + if (StringUtils.isNotBlank(code) && StringUtils.isNotBlank(name)) { + return code + "-" + name; + } + return code + name; + }) + .filter(StringUtils::isNotBlank) + .collect(Collectors.joining(",")); + + productDeviceDisplayMap.put(productId, deviceDisplay); + } + + List resList = BeanUtils.toBean(list, TaskDetailRespVO.class, item -> { MapUtils.findAndThen(map, item.getProductId(), product -> item.setProductName(product.getName()).setBarCode(product.getBarCode())); MapUtils.findAndThen(unitMap, item.getUnitId(), unit -> item.setUnitName(unit.getName())); + + item.setDeviceDisplayName(productDeviceDisplayMap.getOrDefault(item.getProductId(), "")); }); + for (TaskDetailRespVO respVO : resList) { - Long number = planMapper.selectSumTaskDetail(respVO.getId(),null); + Long number = planMapper.selectSumTaskDetail(respVO.getId(), null); respVO.setPlanNumber(number); TaskDO taskDO = taskMapper.selectOne(Wrappers.lambdaQuery().eq(TaskDO::getId, respVO.getTaskId())); - respVO.setTaskCode(taskDO !=null && StringUtils.isNotBlank(taskDO.getCode()) ? taskDO.getCode() : ""); - + respVO.setTaskCode(taskDO != null && StringUtils.isNotBlank(taskDO.getCode()) ? taskDO.getCode() : ""); } return resList; } + @Override public Long createTaskDetail(TaskDetailDO taskDetail) { taskDetailMapper.insert(taskDetail);