Merge remote-tracking branch '惠信/qms/develop' into qms/develop

This commit is contained in:
曹鹏飞 2026-06-13 15:50:23 +08:00
commit e373b39379
4 changed files with 107 additions and 210 deletions

View File

@ -21,7 +21,15 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -41,7 +49,7 @@ public class QmsPdiComponentBindingControllerService {
private final IFileUploadRecordService fileUploadRecordService; private final IFileUploadRecordService fileUploadRecordService;
/** /**
* 保存PDI部件绑定PDI标准检测规则整单覆盖 * 保存PDI部件绑定当前图片覆盖重建
*/ */
@Transactional @Transactional
public void save(QmsPdiComponentBindingSaveQO request) { public void save(QmsPdiComponentBindingSaveQO request) {
@ -49,35 +57,34 @@ public class QmsPdiComponentBindingControllerService {
componentBindingService.lambdaUpdate() componentBindingService.lambdaUpdate()
.eq(QmsPdiComponentBinding::getPdiDetectionRulesId, request.getPdiDetectionRulesId()) .eq(QmsPdiComponentBinding::getPdiDetectionRulesId, request.getPdiDetectionRulesId())
.eq(QmsPdiComponentBinding::getUploadImageId, request.getUploadImageId())
.remove(); .remove();
List<QmsPdiComponentBinding> bindings = new ArrayList<>(); if (CollectionUtil.isEmpty(request.getComponents())) {
for (QmsPdiComponentBindingSaveQO.ImageBindingQO image : request.getItems()) { return;
boolean hasComponentBinding = false; }
if (CollectionUtil.isEmpty(image.getComponents())) {
bindings.add(new QmsPdiComponentBinding()
.setPdiDetectionRulesId(request.getPdiDetectionRulesId())
.setUploadImageId(image.getUploadImageId()));
continue;
}
for (QmsPdiComponentBindingSaveQO.ComponentBindingQO component : image.getComponents()) { Set<String> componentNames = request.getComponents().stream()
if (component.getPdiComponentId() == null) { .map(QmsPdiComponentBindingSaveQO.ComponentBindingQO::getComponentName)
continue; .filter(StrUtil::isNotBlank)
} .collect(Collectors.toSet());
hasComponentBinding = true; Map<String, List<QmsPdiComponentAnagement>> componentMap =
getComponentMapByName(request.getPdiDetectionRulesId(), componentNames);
List<QmsPdiComponentBinding> bindings = new ArrayList<>();
for (QmsPdiComponentBindingSaveQO.ComponentBindingQO component : request.getComponents()) {
List<QmsPdiComponentAnagement> matchedComponents = componentMap.get(component.getComponentName());
if (CollectionUtil.isEmpty(matchedComponents)) {
throw new NflgException(STATE.BusinessError, "部件名称不存在:" + component.getComponentName());
}
for (QmsPdiComponentAnagement matchedComponent : matchedComponents) {
bindings.add(new QmsPdiComponentBinding() bindings.add(new QmsPdiComponentBinding()
.setPdiDetectionRulesId(request.getPdiDetectionRulesId()) .setPdiDetectionRulesId(request.getPdiDetectionRulesId())
.setUploadImageId(image.getUploadImageId()) .setUploadImageId(request.getUploadImageId())
.setPdiComponentId(component.getPdiComponentId()) .setPdiComponentId(matchedComponent.getId())
.setXCoordinatePoint(component.getXCoordinatePoint()) .setXCoordinatePoint(component.getXCoordinatePoint())
.setYCoordinatePoint(component.getYCoordinatePoint()) .setYCoordinatePoint(component.getYCoordinatePoint())
.setStatus(component.getStatus())); .setStatus(matchedComponent.getStatus()));
}
if (!hasComponentBinding) {
bindings.add(new QmsPdiComponentBinding()
.setPdiDetectionRulesId(request.getPdiDetectionRulesId())
.setUploadImageId(image.getUploadImageId()));
} }
} }
@ -87,7 +94,7 @@ public class QmsPdiComponentBindingControllerService {
} }
/** /**
* 查询PDI部件绑定 * 查询PDI部件绑定
*/ */
public QmsPdiComponentBindingSearchVO search(Long pdiDetectionRulesId) { public QmsPdiComponentBindingSearchVO search(Long pdiDetectionRulesId) {
QmsPdiComponentBindingSearchVO vo = new QmsPdiComponentBindingSearchVO(); QmsPdiComponentBindingSearchVO vo = new QmsPdiComponentBindingSearchVO();
@ -156,21 +163,10 @@ public class QmsPdiComponentBindingControllerService {
} }
/** /**
* 分页查询标准检测中已有检测项的部件同名静态/动态部件合并返回 * 分页查询标准检测中已有检测项的部件返回去重后的部件名称
*/ */
public PageData<QmsPdiComponentBindingComponentVO> searchComponents(QmsPdiComponentBindingComponentSearchQO request) { public PageData<QmsPdiComponentBindingComponentVO> searchComponents(QmsPdiComponentBindingComponentSearchQO request) {
List<Long> componentIds = statusItemService.lambdaQuery() List<Long> componentIds = getUsedComponentIds(request.getDetectionRulesId());
.select(QmsPdiDetectionRulesStatusItem::getComponentsId)
.eq(QmsPdiDetectionRulesStatusItem::getDetectionRulesId, request.getDetectionRulesId())
.in(QmsPdiDetectionRulesStatusItem::getStatus, (int) STATIC_STATUS, (int) DYNAMIC_STATUS)
.isNotNull(QmsPdiDetectionRulesStatusItem::getComponentsId)
.list()
.stream()
.map(QmsPdiDetectionRulesStatusItem::getComponentsId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(componentIds)) { if (CollectionUtil.isEmpty(componentIds)) {
return pageComponents(request, List.of()); return pageComponents(request, List.of());
} }
@ -180,109 +176,79 @@ public class QmsPdiComponentBindingControllerService {
.in(QmsPdiComponentAnagement::getId, componentIds) .in(QmsPdiComponentAnagement::getId, componentIds)
.list(); .list();
components.sort(Comparator Map<String, Integer> sortMap = new LinkedHashMap<>();
.comparing(QmsPdiComponentAnagement::getSort, Comparator.nullsLast(Integer::compareTo))
.thenComparing(QmsPdiComponentAnagement::getComponentName, Comparator.nullsLast(String::compareTo))
.thenComparing(QmsPdiComponentAnagement::getStatus, Comparator.nullsLast(Short::compareTo))
.thenComparing(QmsPdiComponentAnagement::getId, Comparator.nullsLast(Long::compareTo)));
Map<String, QmsPdiComponentBindingComponentVO> groupMap = new LinkedHashMap<>();
for (QmsPdiComponentAnagement component : components) { for (QmsPdiComponentAnagement component : components) {
String componentName = component.getComponentName(); String componentName = component.getComponentName();
QmsPdiComponentBindingComponentVO groupVO = groupMap.computeIfAbsent(componentName, name -> { Integer currentSort = sortMap.get(componentName);
QmsPdiComponentBindingComponentVO vo = new QmsPdiComponentBindingComponentVO(); if (!sortMap.containsKey(componentName)
vo.setComponentName(name); || currentSort == null
vo.setSort(component.getSort()); || (component.getSort() != null && component.getSort() < currentSort)) {
return vo; sortMap.put(componentName, component.getSort());
});
if (groupVO.getSort() == null
|| (component.getSort() != null && component.getSort() < groupVO.getSort())) {
groupVO.setSort(component.getSort());
} }
QmsPdiComponentBindingComponentVO.ComponentStatusVO statusVO =
new QmsPdiComponentBindingComponentVO.ComponentStatusVO();
statusVO.setComponentId(component.getId());
statusVO.setStatus(component.getStatus());
statusVO.setStatusName(getStatusName(component.getStatus()));
groupVO.getComponents().add(statusVO);
} }
List<QmsPdiComponentBindingComponentVO> groupedComponents = new ArrayList<>(groupMap.values()); List<QmsPdiComponentBindingComponentVO> groupedComponents = sortMap.entrySet().stream()
groupedComponents.forEach(group -> group.getComponents().sort(Comparator .sorted(Map.Entry.<String, Integer>comparingByValue(Comparator.nullsLast(Integer::compareTo))
.comparing(QmsPdiComponentBindingComponentVO.ComponentStatusVO::getStatus, Comparator.nullsLast(Short::compareTo)) .thenComparing(Map.Entry.comparingByKey(Comparator.nullsLast(String::compareTo))))
.thenComparing(QmsPdiComponentBindingComponentVO.ComponentStatusVO::getComponentId, Comparator.nullsLast(Long::compareTo)))); .map(entry -> {
groupedComponents.sort(Comparator QmsPdiComponentBindingComponentVO vo = new QmsPdiComponentBindingComponentVO();
.comparing(QmsPdiComponentBindingComponentVO::getSort, Comparator.nullsLast(Integer::compareTo)) vo.setComponentName(entry.getKey());
.thenComparing(QmsPdiComponentBindingComponentVO::getComponentName, Comparator.nullsLast(String::compareTo))); return vo;
})
.collect(Collectors.toList());
return pageComponents(request, groupedComponents); return pageComponents(request, groupedComponents);
} }
private void validateSaveRequest(QmsPdiComponentBindingSaveQO request) { private void validateSaveRequest(QmsPdiComponentBindingSaveQO request) {
Set<Long> imageIds = request.getItems().stream() if (fileUploadRecordService.getById(request.getUploadImageId()) == null) {
.peek(image -> {
if (image == null) {
throw new NflgException(STATE.BusinessError, "图片绑定对象不能为空");
}
})
.map(QmsPdiComponentBindingSaveQO.ImageBindingQO::getUploadImageId)
.collect(Collectors.toSet());
List<FileUploadRecord> images = fileUploadRecordService.listByIds(imageIds);
if (images.size() != imageIds.size()) {
throw new NflgException(STATE.BusinessError, "上传图片不存在"); throw new NflgException(STATE.BusinessError, "上传图片不存在");
} }
if (CollectionUtil.isEmpty(request.getComponents())) {
Set<Long> componentIds = new HashSet<>();
Map<String, Set<Short>> coordinateStatusMap = new HashMap<>();
for (QmsPdiComponentBindingSaveQO.ImageBindingQO image : request.getItems()) {
if (CollectionUtil.isEmpty(image.getComponents())) {
continue;
}
for (QmsPdiComponentBindingSaveQO.ComponentBindingQO component : image.getComponents()) {
if (component == null) {
throw new NflgException(STATE.BusinessError, "部件绑定对象不能为空");
}
if (component.getPdiComponentId() == null) {
if (hasBindingValue(component)) {
throw new NflgException(STATE.BusinessError, "部件ID为空时不能传入坐标或状态");
}
continue;
}
if (StrUtil.isBlank(component.getXCoordinatePoint()) || StrUtil.isBlank(component.getYCoordinatePoint())) {
throw new NflgException(STATE.BusinessError, "绑定部件时x轴坐标和y轴坐标不能为空");
}
if (!isAllowedStatus(component.getStatus())) {
throw new NflgException(STATE.BusinessError, "状态只能为0静态或1动态");
}
componentIds.add(component.getPdiComponentId());
String coordinateKey = coordinateKey(image.getUploadImageId(), component.getXCoordinatePoint(), component.getYCoordinatePoint());
Set<Short> statuses = coordinateStatusMap.computeIfAbsent(coordinateKey, key -> new HashSet<>());
if (!statuses.add(component.getStatus())) {
throw new NflgException(STATE.BusinessError, "同一图片同一坐标不能重复绑定相同状态");
}
if (statuses.size() > 2) {
throw new NflgException(STATE.BusinessError, "同一图片同一坐标最多绑定一个静态和一个动态部件");
}
}
}
if (CollectionUtil.isEmpty(componentIds)) {
return; return;
} }
for (QmsPdiComponentBindingSaveQO.ComponentBindingQO component : request.getComponents()) {
if (component == null) {
throw new NflgException(STATE.BusinessError, "部件绑定对象不能为空");
}
if (StrUtil.isBlank(component.getComponentName())) {
throw new NflgException(STATE.BusinessError, "部件名称不能为空");
}
if (StrUtil.isBlank(component.getXCoordinatePoint()) || StrUtil.isBlank(component.getYCoordinatePoint())) {
throw new NflgException(STATE.BusinessError, "绑定部件时x轴坐标和y轴坐标不能为空");
}
}
}
Set<Long> validComponentIds = componentService.lambdaQuery() private Map<String, List<QmsPdiComponentAnagement>> getComponentMapByName(Long detectionRulesId, Set<String> componentNames) {
.select(QmsPdiComponentAnagement::getId) if (CollectionUtil.isEmpty(componentNames)) {
.eq(QmsPdiComponentAnagement::getDetectionRulesId, request.getPdiDetectionRulesId()) return Collections.emptyMap();
}
List<Long> componentIds = getUsedComponentIds(detectionRulesId);
if (CollectionUtil.isEmpty(componentIds)) {
return Collections.emptyMap();
}
return componentService.lambdaQuery()
.eq(QmsPdiComponentAnagement::getDetectionRulesId, detectionRulesId)
.in(QmsPdiComponentAnagement::getId, componentIds) .in(QmsPdiComponentAnagement::getId, componentIds)
.in(QmsPdiComponentAnagement::getComponentName, componentNames)
.list() .list()
.stream() .stream()
.map(QmsPdiComponentAnagement::getId) .collect(Collectors.groupingBy(QmsPdiComponentAnagement::getComponentName, LinkedHashMap::new, Collectors.toList()));
.collect(Collectors.toSet()); }
if (validComponentIds.size() != componentIds.size()) {
throw new NflgException(STATE.BusinessError, "存在不属于当前PDI标准检测规则的部件"); private List<Long> getUsedComponentIds(Long detectionRulesId) {
} return statusItemService.lambdaQuery()
.select(QmsPdiDetectionRulesStatusItem::getComponentsId)
.eq(QmsPdiDetectionRulesStatusItem::getDetectionRulesId, detectionRulesId)
.in(QmsPdiDetectionRulesStatusItem::getStatus, (int) STATIC_STATUS, (int) DYNAMIC_STATUS)
.isNotNull(QmsPdiDetectionRulesStatusItem::getComponentsId)
.list()
.stream()
.map(QmsPdiDetectionRulesStatusItem::getComponentsId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
} }
private Map<Long, FileUploadRecord> getImageMap(List<QmsPdiComponentBinding> bindings) { private Map<Long, FileUploadRecord> getImageMap(List<QmsPdiComponentBinding> bindings) {
@ -361,30 +327,10 @@ public class QmsPdiComponentBindingControllerService {
return status != null && (status == STATIC_STATUS || status == DYNAMIC_STATUS); return status != null && (status == STATIC_STATUS || status == DYNAMIC_STATUS);
} }
private boolean hasBindingValue(QmsPdiComponentBindingSaveQO.ComponentBindingQO component) {
return StrUtil.isNotBlank(component.getXCoordinatePoint())
|| StrUtil.isNotBlank(component.getYCoordinatePoint())
|| component.getStatus() != null;
}
private String coordinateKey(Long uploadImageId, String xCoordinatePoint, String yCoordinatePoint) {
return uploadImageId + "|" + xCoordinatePoint + "|" + yCoordinatePoint;
}
private String componentStatusKey(Long componentId, Short status) { private String componentStatusKey(Long componentId, Short status) {
return componentId + "|" + status; return componentId + "|" + status;
} }
private String getStatusName(Short status) {
if (Objects.equals(status, STATIC_STATUS)) {
return "静态";
}
if (Objects.equals(status, DYNAMIC_STATUS)) {
return "动态";
}
return null;
}
private PageData<QmsPdiComponentBindingComponentVO> pageComponents( private PageData<QmsPdiComponentBindingComponentVO> pageComponents(
QmsPdiComponentBindingComponentSearchQO request, QmsPdiComponentBindingComponentSearchQO request,
List<QmsPdiComponentBindingComponentVO> components) { List<QmsPdiComponentBindingComponentVO> components) {

View File

@ -1,16 +1,15 @@
package com.nflg.wms.common.pojo.qo; package com.nflg.wms.common.pojo.qo;
import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
/** /**
* PDI部件绑定 保存请求参数 * PDI部件绑定保存请求参数
*/ */
@Data @Data
public class QmsPdiComponentBindingSaveQO { public class QmsPdiComponentBindingSaveQO {
@ -23,55 +22,39 @@ public class QmsPdiComponentBindingSaveQO {
private Long pdiDetectionRulesId; private Long pdiDetectionRulesId;
/** /**
* 图片绑定列表 * 上传图片ID
*/
@NotNull(message = "上传图片ID不能为空")
@JsonAlias("upload_image_id")
private Long uploadImageId;
/**
* 部件绑定列表
*/ */
@Valid @Valid
@NotEmpty(message = "图片绑定列表不能为空") private List<ComponentBindingQO> components;
private List<ImageBindingQO> items;
@Data
public static class ImageBindingQO {
/**
* 上传图片的ID
*/
@NotNull(message = "上传图片ID不能为空")
@JsonAlias("upload_image_id")
private Long uploadImageId;
/**
* 部件绑定列表
*/
@Valid
private List<ComponentBindingQO> components;
}
@Data @Data
public static class ComponentBindingQO { public static class ComponentBindingQO {
/** /**
* 部件ID * 部件名称
*/ */
@JsonAlias("pdi_component_id") @NotBlank(message = "部件名称不能为空")
private Long pdiComponentId; private String componentName;
/** /**
* x轴坐标 * x轴坐标
*/ */
@JsonProperty("xCoordinatePoint") @NotBlank(message = "x轴坐标不能为空")
@JsonAlias({"x_coordinate_point", "XCoordinatePoint"}) @JsonAlias({"x_coordinate_point", "XCoordinatePoint"})
private String xCoordinatePoint; private String xCoordinatePoint;
/** /**
* y轴坐标 * y轴坐标
*/ */
@JsonProperty("yCoordinatePoint") @NotBlank(message = "y轴坐标不能为空")
@JsonAlias({"y_coordinate_point", "YCoordinatePoint"}) @JsonAlias({"y_coordinate_point", "YCoordinatePoint"})
private String yCoordinatePoint; private String yCoordinatePoint;
/**
* 状态0为静态1为动态
*/
private Short status;
} }
} }

View File

@ -2,9 +2,6 @@ package com.nflg.wms.common.pojo.vo;
import lombok.Data; import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/** /**
* PDI部件绑定-标准检测部件分页查询返回值 * PDI部件绑定-标准检测部件分页查询返回值
*/ */
@ -15,33 +12,4 @@ public class QmsPdiComponentBindingComponentVO {
* 部件名称 * 部件名称
*/ */
private String componentName; private String componentName;
/**
* 部件排序
*/
private Integer sort;
/**
* 同名部件下不同检测状态的部件ID
*/
private List<ComponentStatusVO> components = new ArrayList<>();
@Data
public static class ComponentStatusVO {
/**
* 部件ID
*/
private Long componentId;
/**
* 状态0=静态1=动态
*/
private Short status;
/**
* 状态名称
*/
private String statusName;
}
} }

View File

@ -12,7 +12,7 @@
t.warehouse_no AS warehouseNo, t.warehouse_no AS warehouseNo,
r.inspection_type AS inspectionType, r.inspection_type AS inspectionType,
r.inspection_version AS inspectionVersion, r.inspection_version AS inspectionVersion,
r.model_no AS machineNo, r.model_no AS modelNo,
t.inspection_enable AS inspectionEnable, t.inspection_enable AS inspectionEnable,
t.inspection_inspection AS inspectionInspection, t.inspection_inspection AS inspectionInspection,
ui.user_name AS inspectorName, ui.user_name AS inspectorName,
@ -75,7 +75,7 @@
t.warehouse_no AS warehouseNo, t.warehouse_no AS warehouseNo,
r.inspection_type AS inspectionType, r.inspection_type AS inspectionType,
r.inspection_version AS inspectionVersion, r.inspection_version AS inspectionVersion,
r.model_no AS machineNo, r.model_no AS modelNo,
t.inspection_enable AS inspectionEnable, t.inspection_enable AS inspectionEnable,
t.inspection_inspection AS inspectionInspection, t.inspection_inspection AS inspectionInspection,
ui.user_name AS inspectorName, ui.user_name AS inspectorName,