package cn.iocoder.yudao.module.mdm.service.item; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemTechnicalFileCreateReqVO; import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemTechnicalFileRespVO; import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemTechnicalFileDO; import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemTechnicalFileMapper; import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mdm.enums.ErrorCodeConstants.MDM_ITEM_NOT_EXISTS; @Service public class MdmItemTechnicalFileServiceImpl implements MdmItemTechnicalFileService { private static final String RECORD_TYPE = "mdm_item_technical_file"; private final MdmItemTechnicalFileMapper mapper; private final MdmItemService itemService; private final StorageAttachmentApi storageAttachmentApi; public MdmItemTechnicalFileServiceImpl(MdmItemTechnicalFileMapper mapper, MdmItemService itemService, StorageAttachmentApi storageAttachmentApi) { this.mapper = mapper; this.itemService = itemService; this.storageAttachmentApi = storageAttachmentApi; } @Override @Transactional(rollbackFor = Exception.class) public Long createTechnicalFile(MdmItemTechnicalFileCreateReqVO reqVO) { if (itemService.getItem(reqVO.getItemId()) == null) { throw exception(MDM_ITEM_NOT_EXISTS); } int version = mapper.selectMaxVersionNo(reqVO.getItemId()) + 1; // 记录 ID 必须与附件关系记录 ID 一致,因此先插入版本记录,再绑定附件。 MdmItemTechnicalFileDO file = new MdmItemTechnicalFileDO(); file.setItemId(reqVO.getItemId()); file.setStorageBlobId(reqVO.getBlobId()); file.setVersionNo(version); mapper.insert(file); storageAttachmentApi.bindAttachments("file", RECORD_TYPE, file.getId(), Collections.singletonList(reqVO.getBlobId())); return file.getId(); } @Override @Transactional(rollbackFor = Exception.class) public void deleteTechnicalFile(Long itemId, Long id) { MdmItemTechnicalFileDO file = mapper.selectById(id); if (file == null || !java.util.Objects.equals(file.getItemId(), itemId)) { throw new cn.iocoder.yudao.framework.common.exception.ServiceException(400, "技术文件不存在或不属于该物料"); } // 只移除物料的当前文件记录。保留附件及文件本体,供已有工单快照使用。 mapper.deleteById(id); } @Override public List getTechnicalFileList(Long itemId) { return mapper.selectListByItemId(itemId).stream().map(file -> { MdmItemTechnicalFileRespVO resp = BeanUtils.toBean(file, MdmItemTechnicalFileRespVO.class); resp.setBlobId(file.getStorageBlobId()); List blobs = storageAttachmentApi.listAttachments(RECORD_TYPE, file.getId()); if (blobs != null && !blobs.isEmpty()) { StorageBlobRespDTO blob = blobs.get(0); resp.setFileName(blob.getName()); resp.setPreviewURL(blob.getPreviewURL()); resp.setDownloadURL(blob.getDownloadURL()); } return resp; }).toList(); } }