package cn.iocoder.yudao.module.mes.controller.admin.qc.attachment; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcService; import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; import jakarta.annotation.Resource; import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; import lombok.Data; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; /** 质检附件独立于检验结论,上传附件不自动将产品判为合格。 */ @RestController @RequestMapping("/mes/qc/attachment") @Validated public class MesQcAttachmentController { @Resource private MesQcIqcService iqcService; @Resource private MesQcIpqcService ipqcService; @Resource private MesQcOqcService oqcService; @Resource private MesQcRqcService rqcService; @Resource private cn.iocoder.yudao.module.mes.controller.admin.qc.patrol.PatrolMapper patrolMapper; @Resource private StorageAttachmentApi storageApi; @Resource private org.springframework.jdbc.core.JdbcTemplate jdbcTemplate; @GetMapping("/list") @PreAuthorize("@ss.hasPermission('mes:qc-' + #type.toLowerCase() + ':query')") public CommonResult> list( @RequestParam @Pattern(regexp = "iqc|ipqc|oqc|rqc|patrol") String type, @RequestParam @NotNull Long id) { validateDocument(type, id); var files = storageApi.listAttachments(recordType(type), id); return success(files == null ? List.of() : files); } @PutMapping("/save") @PreAuthorize("@ss.hasPermission('mes:qc-' + #req.type.toLowerCase() + ':update')") @Transactional(rollbackFor = Exception.class) public CommonResult save(@Valid @RequestBody SaveReq req) { lockDocument(req.getType(), req.getId()); validateDocument(req.getType(), req.getId()); // bindAttachments 仅替换关联,不删除共享文件本体。 storageApi.bindAttachments("file", recordType(req.getType()), req.getId(), req.getBlobIds().stream().distinct().toList()); return success(true); } @PostMapping("/append") @PreAuthorize("@ss.hasPermission('mes:qc-' + #req.type.toLowerCase() + ':update')") @Transactional(rollbackFor = Exception.class) public CommonResult append(@Valid @RequestBody AppendReq req) { lockDocument(req.getType(), req.getId()); validateDocument(req.getType(), req.getId()); var existing = storageApi.listAttachments(recordType(req.getType()), req.getId()); var ids = new java.util.LinkedHashSet(); if (existing != null) existing.forEach(blob -> ids.add(blob.getId())); ids.add(req.getBlobId()); if (ids.size() > 50) throw new ServiceException(400, "每张质检单最多上传50份附件"); storageApi.bindAttachments("file", recordType(req.getType()), req.getId(), List.copyOf(ids)); return success(true); } @DeleteMapping("/remove") @PreAuthorize("@ss.hasPermission('mes:qc-' + #type.toLowerCase() + ':update')") @Transactional(rollbackFor = Exception.class) public CommonResult remove( @RequestParam @Pattern(regexp = "iqc|ipqc|oqc|rqc|patrol") String type, @RequestParam @NotNull Long id, @RequestParam @NotNull Long blobId) { lockDocument(type, id); validateDocument(type, id); storageApi.removeReference("file", recordType(type), id, blobId); return success(true); } private String recordType(String type) { return switch (type) { case "iqc", "ipqc", "oqc", "rqc", "patrol" -> "mes_qc_" + type + "_attachment"; default -> throw new ServiceException(400, "质检类型无效"); }; } private void lockDocument(String type, Long id) { String table = switch (type) { case "iqc" -> "mes_qc_iqc"; case "ipqc" -> "mes_qc_ipqc"; case "oqc" -> "mes_qc_oqc"; case "rqc" -> "mes_qc_rqc"; case "patrol" -> "mes_qc_patrol"; default -> throw new ServiceException(400, "质检类型无效"); }; var ids = jdbcTemplate.queryForList("SELECT id FROM " + table + " WHERE id = ? AND deleted = 0 FOR UPDATE", Long.class, id); if (ids.isEmpty()) throw new ServiceException(400, "质检单不存在"); } private Integer validateDocument(String type, Long id) { return switch (type) { case "iqc" -> iqcService.validateIqcExists(id).getStatus(); case "ipqc" -> ipqcService.validateIpqcExists(id).getStatus(); case "oqc" -> oqcService.validateOqcExists(id).getStatus(); case "rqc" -> rqcService.validateRqcExists(id).getStatus(); case "patrol" -> { if (patrolMapper.selectById(id) == null) throw new ServiceException(400, "巡检记录不存在"); yield 0; } default -> throw new ServiceException(400, "质检类型无效"); }; } @Data public static class SaveReq { @NotNull @Pattern(regexp = "iqc|ipqc|oqc|rqc|patrol") private String type; @NotNull private Long id; @NotEmpty @Size(max = 50) private List<@NotNull Long> blobIds; } @Data public static class AppendReq { @NotNull @Pattern(regexp = "iqc|ipqc|oqc|rqc|patrol") private String type; @NotNull private Long id; @NotNull private Long blobId; } }