diff --git a/src/main/java/com/ai/da/common/config/ThreeDSave.java b/src/main/java/com/ai/da/common/config/ThreeDSave.java new file mode 100644 index 00000000..b9f183a2 --- /dev/null +++ b/src/main/java/com/ai/da/common/config/ThreeDSave.java @@ -0,0 +1,127 @@ +package com.ai.da.common.config; + +import com.ai.da.common.utils.MinioUtil; +import com.ai.da.mapper.primary.ThreeDDetailMapper; +import com.ai.da.mapper.primary.ThreeDSimpleMapper; +import com.ai.da.mapper.primary.entity.ThreeDDetail; +import com.ai.da.mapper.primary.entity.ThreeDSimple; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Component +public class ThreeDSave { + + @Resource + private ThreeDDetailMapper threeDDetailMapper; + @Resource + private ThreeDSimpleMapper threeDSimpleMapper; + @Resource + private MinioUtil minioUtil; + @PostConstruct + public void test() { +// minioSave(); + } + + private void minioSave() { + // 指定目标文件夹路径 + String folderPath = "C:\\workspace\\3D\\3D虚拟 1-7\\3D服装整理\\femaleZip"; + + // 创建文件对象 + File folder = new File(folderPath); + + // 检查文件夹是否存在且是目录 + if (folder.exists() && folder.isDirectory()) { + // 获取所有 .zip 文件 + File[] zipFiles = folder.listFiles((dir, name) -> name.toLowerCase().endsWith(".zip")); + + List zipFileNameList = new ArrayList<>(); + // 输出文件名 + if (zipFiles != null) { + for (File file : zipFiles) { + String zipFileName = file.getName(); + String[] split = zipFileName.split("_"); + String zipName = split[0]; + String sizeWithSuffix = split[1]; + String[] sizeWithSuffixSplit = sizeWithSuffix.split("\\."); + String size = sizeWithSuffixSplit[0]; + // 找到第一个字母的位置 + int index = 0; + while (index < size.length() && Character.UnicodeBlock.of(size.charAt(index)) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) { + index++; + } + + if (index > 0 && index < size.length()) { + String prefix = size.substring(0, index); // "亚码" + String suffix = size.substring(index); // "L" + + ThreeDDetail threeDDetail = new ThreeDDetail(); + threeDDetail.setName(zipFileName); + String url = "aida-threed/female/zip/" + zipFileName; + threeDDetail.setGender("female"); + threeDDetail.setSizeType(prefix); + threeDDetail.setSize(suffix); + threeDDetail.setUrl(url); + threeDDetailMapper.insert(threeDDetail); + minioUtil.upload(url, file); + + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(ThreeDSimple::getName, zipName); + qw.lambda().eq(ThreeDSimple::getGender, "female"); + List threeDSimples = threeDSimpleMapper.selectList(qw); + + if (CollectionUtils.isEmpty(threeDSimples)) { + ThreeDSimple threeDSimple = new ThreeDSimple(); + threeDSimple.setName(zipName); + threeDSimple.setGender("female"); + + String glbPath = "C:\\workspace\\3D\\3D虚拟 1-7\\3D服装整理\\female\\" + zipName + "\\" +"亚码L"; + File glbFolder = new File(glbPath); + + // 查找 .glb 文件 + if (glbFolder.exists() && glbFolder.isDirectory()) { + File[] glbFiles = glbFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".glb")); + if (glbFiles != null && glbFiles.length > 0) { + for (File glbFile : glbFiles) { + String name = glbFile.getName(); + String glbUrl = "aida-threed/female/glb/" + name; + threeDSimple.setUrl(glbUrl); + minioUtil.upload(glbUrl, glbFile); + } + } else { + System.out.println("未找到 GLB 文件。" + glbFolder); + } + } else { + System.out.println("GLB 文件夹不存在: " + glbPath); + } + threeDSimpleMapper.insert(threeDSimple); + threeDDetail.setThreeDSimpleId(threeDSimple.getId()); + threeDDetailMapper.updateById(threeDDetail); + }else { + Long id = threeDSimples.get(0).getId(); + threeDDetail.setThreeDSimpleId(id); + threeDDetailMapper.updateById(threeDDetail); + } + + } else { + + } + + } + } else { + System.out.println("未找到 ZIP 文件。"); + } + log.info("aaa"); + } else { + System.out.println("文件夹不存在或不是一个目录。"); + } + } +} diff --git a/src/main/java/com/ai/da/common/utils/MinioUtil.java b/src/main/java/com/ai/da/common/utils/MinioUtil.java index f622b66f..6e9dd42e 100644 --- a/src/main/java/com/ai/da/common/utils/MinioUtil.java +++ b/src/main/java/com/ai/da/common/utils/MinioUtil.java @@ -570,6 +570,36 @@ public class MinioUtil { throw new BusinessException(e.getMessage()); } } + + public void upload(String url, File file) { + try { + // 分割桶名和对象路径 + int firstSlashIndex = url.indexOf("/"); + if (firstSlashIndex == -1) { + throw new IllegalArgumentException("URL 格式不正确,无法解析桶名和对象路径"); + } + String bucketName = url.substring(0, firstSlashIndex); + String objectName = url.substring(firstSlashIndex + 1); + + // 读取文件流 + try (FileInputStream fileInputStream = new FileInputStream(file)) { + // 上传到 MinIO + minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .stream(fileInputStream, file.length(), -1) + .contentType("application/zip") + .build() + ); + System.out.println("文件上传成功: " + url); + } + } catch (Exception e) { + e.printStackTrace(); + System.err.println("文件上传失败: " + e.getMessage()); + } + } + } diff --git a/src/main/java/com/ai/da/controller/ProjectController.java b/src/main/java/com/ai/da/controller/ProjectController.java index 9b86ed41..26cfe7fd 100644 --- a/src/main/java/com/ai/da/controller/ProjectController.java +++ b/src/main/java/com/ai/da/controller/ProjectController.java @@ -3,25 +3,23 @@ package com.ai.da.controller; import com.ai.da.common.response.PageBaseResponse; import com.ai.da.common.response.Response; import com.ai.da.mapper.primary.entity.LibraryModelPoint; -import com.ai.da.model.dto.MannequinDTO; -import com.ai.da.model.dto.ModuleSaveDTO; -import com.ai.da.model.dto.ProjectDTO; -import com.ai.da.model.dto.ProjectQueryDTO; +import com.ai.da.mapper.primary.entity.ThreeDLayout; +import com.ai.da.model.dto.*; import com.ai.da.model.enums.MannequinType; import com.ai.da.model.vo.*; import com.ai.da.service.UserLikeGroupService; import com.ai.da.service.WorkspaceService; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import io.minio.errors.MinioException; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import java.io.IOException; @Api(tags = "Project模块") @Slf4j @@ -90,4 +88,39 @@ public class ProjectController { public Response getMannequinDetail(@Valid @RequestBody MannequinDTO mannequinDTO) { return Response.success(userLikeGroupService.getMannequinDetail(mannequinDTO)); } + + @PostMapping("/threeDPage") + @ApiOperationSupport(order = 8) + @ApiOperation(value = "获取3Dpage", notes = "传入ThreeDLayoutQueryDTO") + public Response> threeDPage(@Valid @RequestBody ThreeDLayoutQueryDTO threeDLayoutQueryDTO) { + return Response.success(PageBaseResponse.success(userLikeGroupService.getThreeDLayoutPage(threeDLayoutQueryDTO))); + } + + @PostMapping("/getLayoutDetail") + @ApiOperationSupport(order = 9) + @ApiOperation(value = "获取3D详情", notes = "传入project") + public Response getLayoutDetail(@RequestParam(value = "threeDSimpleId") Long threeDSimpleId) { + return Response.success(userLikeGroupService.getLayoutDetail(threeDSimpleId)); + } + + @PostMapping("/getThreeDSize") + @ApiOperationSupport(order = 10) + @ApiOperation(value = "获取尺码", notes = "传入project") + public Response getThreeDSize(@RequestParam(value = "threeDSimpleId") Long threeDSimpleId) { + return Response.success(userLikeGroupService.getThreeDSize(threeDSimpleId)); + } + + @GetMapping("/getThreeDGlb") + @ApiOperationSupport(order = 11) + @ApiOperation(value = "获取GLB", notes = "传入project") + public void getThreeDGlb(@RequestParam(value = "threeDSimpleId") Long threeDSimpleId, HttpServletResponse response) throws MinioException, IOException { + userLikeGroupService.getThreeDGlb(threeDSimpleId, response); + } + + @GetMapping("/downloadZip") + @ApiOperationSupport(order = 11) + @ApiOperation(value = "下载", notes = "传入project") + public void downloadZip(@RequestParam(value = "threeDSimpleId") Long threeDSimpleId, @RequestParam(value = "sizeType") String sizeType, @RequestParam(value = "size") String size, HttpServletResponse response) throws MinioException, IOException { + userLikeGroupService.downloadZip(threeDSimpleId, sizeType, size, response); + } } diff --git a/src/main/java/com/ai/da/controller/SavedCollectionController.java b/src/main/java/com/ai/da/controller/SavedCollectionController.java index 63fc15d7..d507f849 100644 --- a/src/main/java/com/ai/da/controller/SavedCollectionController.java +++ b/src/main/java/com/ai/da/controller/SavedCollectionController.java @@ -279,7 +279,7 @@ public class SavedCollectionController { @ApiOperation(value = "brandDNAUpload") @PostMapping("/brandDNAUpload") - public Response brandDNAUpload(@RequestParam("file") MultipartFile file, @RequestParam("brandId") Long brandId) throws IOException { + public Response brandDNAUpload(@RequestParam("file") MultipartFile file, @RequestParam("brandId") Long brandId) throws IOException { return Response.success(userLikeGroupService.brandDNAUpload(file, brandId)); } diff --git a/src/main/java/com/ai/da/mapper/primary/ThreeDDetailMapper.java b/src/main/java/com/ai/da/mapper/primary/ThreeDDetailMapper.java new file mode 100644 index 00000000..79bb3ab7 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/ThreeDDetailMapper.java @@ -0,0 +1,7 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.ThreeDDetail; + +public interface ThreeDDetailMapper extends CommonMapper { +} diff --git a/src/main/java/com/ai/da/mapper/primary/ThreeDLayoutMapper.java b/src/main/java/com/ai/da/mapper/primary/ThreeDLayoutMapper.java new file mode 100644 index 00000000..d7a3fbcb --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/ThreeDLayoutMapper.java @@ -0,0 +1,7 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.ThreeDLayout; + +public interface ThreeDLayoutMapper extends CommonMapper { +} diff --git a/src/main/java/com/ai/da/mapper/primary/ThreeDPatternLayoutMapper.java b/src/main/java/com/ai/da/mapper/primary/ThreeDPatternLayoutMapper.java new file mode 100644 index 00000000..91d1fca0 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/ThreeDPatternLayoutMapper.java @@ -0,0 +1,7 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.ThreeDPatternLayout; + +public interface ThreeDPatternLayoutMapper extends CommonMapper { +} diff --git a/src/main/java/com/ai/da/mapper/primary/ThreeDSimpleMapper.java b/src/main/java/com/ai/da/mapper/primary/ThreeDSimpleMapper.java new file mode 100644 index 00000000..063f81bc --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/ThreeDSimpleMapper.java @@ -0,0 +1,7 @@ +package com.ai.da.mapper.primary; + +import com.ai.da.common.config.mybatis.plus.CommonMapper; +import com.ai.da.mapper.primary.entity.ThreeDSimple; + +public interface ThreeDSimpleMapper extends CommonMapper { +} diff --git a/src/main/java/com/ai/da/mapper/primary/entity/ThreeDDetail.java b/src/main/java/com/ai/da/mapper/primary/entity/ThreeDDetail.java new file mode 100644 index 00000000..58a66a2c --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/ThreeDDetail.java @@ -0,0 +1,29 @@ +package com.ai.da.mapper.primary.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("three_d_detail") +public class ThreeDDetail implements Serializable { + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String name; + private String url; + private String gender; + + private String sizeType; + private String size; + + private Long threeDSimpleId; +} diff --git a/src/main/java/com/ai/da/mapper/primary/entity/ThreeDLayout.java b/src/main/java/com/ai/da/mapper/primary/entity/ThreeDLayout.java new file mode 100644 index 00000000..8f2a0adf --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/ThreeDLayout.java @@ -0,0 +1,30 @@ +package com.ai.da.mapper.primary.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("three_d_layout") +public class ThreeDLayout implements Serializable { + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String name; + + private String url; + + private String type; + + private Long threeDSimpleId; + + private String gender; +} \ No newline at end of file diff --git a/src/main/java/com/ai/da/mapper/primary/entity/ThreeDPatternLayout.java b/src/main/java/com/ai/da/mapper/primary/entity/ThreeDPatternLayout.java new file mode 100644 index 00000000..60e37d2d --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/ThreeDPatternLayout.java @@ -0,0 +1,26 @@ +package com.ai.da.mapper.primary.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("three_d_layout") +public class ThreeDPatternLayout implements Serializable { + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String name; + + private String url; + + private Long threeDSimpleId; +} \ No newline at end of file diff --git a/src/main/java/com/ai/da/mapper/primary/entity/ThreeDSimple.java b/src/main/java/com/ai/da/mapper/primary/entity/ThreeDSimple.java new file mode 100644 index 00000000..60a525d8 --- /dev/null +++ b/src/main/java/com/ai/da/mapper/primary/entity/ThreeDSimple.java @@ -0,0 +1,26 @@ +package com.ai.da.mapper.primary.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("three_d_simple") +public class ThreeDSimple implements Serializable { + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String name; + private String url; + private String gender; +} diff --git a/src/main/java/com/ai/da/model/dto/ThreeDLayoutQueryDTO.java b/src/main/java/com/ai/da/model/dto/ThreeDLayoutQueryDTO.java new file mode 100644 index 00000000..37df733f --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/ThreeDLayoutQueryDTO.java @@ -0,0 +1,21 @@ + +package com.ai.da.model.dto; + +import com.ai.da.model.vo.PageQueryBaseVo; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * 数据传输对象实体类 + * + * @author SHAHAIBO + * @since 2023-08-01 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ThreeDLayoutQueryDTO extends PageQueryBaseVo { + +} diff --git a/src/main/java/com/ai/da/model/vo/ThreeDLayoutVO.java b/src/main/java/com/ai/da/model/vo/ThreeDLayoutVO.java new file mode 100644 index 00000000..c8e9b413 --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/ThreeDLayoutVO.java @@ -0,0 +1,8 @@ +package com.ai.da.model.vo; + +import com.ai.da.mapper.primary.entity.ThreeDLayout; +import lombok.Data; + +@Data +public class ThreeDLayoutVO extends ThreeDLayout { +} diff --git a/src/main/java/com/ai/da/model/vo/ThreeDSizeVO.java b/src/main/java/com/ai/da/model/vo/ThreeDSizeVO.java new file mode 100644 index 00000000..1b3389dd --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/ThreeDSizeVO.java @@ -0,0 +1,11 @@ +package com.ai.da.model.vo; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class ThreeDSizeVO { + private Map> sizeTypeMap; +} diff --git a/src/main/java/com/ai/da/model/vo/ThreeDVO.java b/src/main/java/com/ai/da/model/vo/ThreeDVO.java new file mode 100644 index 00000000..2e424433 --- /dev/null +++ b/src/main/java/com/ai/da/model/vo/ThreeDVO.java @@ -0,0 +1,15 @@ +package com.ai.da.model.vo; + +import com.ai.da.mapper.primary.entity.ThreeDLayout; +import com.ai.da.mapper.primary.entity.ThreeDPatternLayout; +import lombok.Data; + +import java.util.List; + +@Data +public class ThreeDVO { + + private List threeDLayoutList; + + private ThreeDPatternLayout threeDPatternLayout; +} diff --git a/src/main/java/com/ai/da/service/UserLikeGroupService.java b/src/main/java/com/ai/da/service/UserLikeGroupService.java index bd8e7c54..7dbdecd7 100644 --- a/src/main/java/com/ai/da/service/UserLikeGroupService.java +++ b/src/main/java/com/ai/da/service/UserLikeGroupService.java @@ -7,8 +7,10 @@ import com.ai.da.model.vo.*; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; +import io.minio.errors.MinioException; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; @@ -86,9 +88,19 @@ public interface UserLikeGroupService extends IService { Boolean brandDNASaveOrUpdate(BrandDNADTO brandDNADTO); - String brandDNAUpload(MultipartFile file, Long brandId) throws IOException; + Library brandDNAUpload(MultipartFile file, Long brandId) throws IOException; PageBaseResponse brandDNAPage(BrandDNAQueryDTO brandDNAQueryDTO); BrandDNAGenerateVO brandDNAGenerate(String prompt); + + IPage getThreeDLayoutPage(ThreeDLayoutQueryDTO threeDLayoutQueryDTO); + + ThreeDVO getLayoutDetail(Long threeDSimpleId); + + ThreeDSizeVO getThreeDSize(Long threeDSimpleId); + + void getThreeDGlb(Long threeDSimpleId, HttpServletResponse response) throws MinioException, IOException; + + void downloadZip(Long threeDSimpleId, String sizeType, String size, HttpServletResponse response) throws MinioException, IOException; } diff --git a/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java b/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java index f1772ccf..ae443a56 100644 --- a/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/UserLikeGroupServiceImpl.java @@ -32,6 +32,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.base.Function; import com.google.gson.Gson; +import io.minio.errors.MinioException; import io.netty.util.internal.StringUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -42,6 +43,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; import java.io.*; import java.time.LocalDateTime; import java.time.ZoneId; @@ -115,6 +117,14 @@ public class UserLikeGroupServiceImpl extends ServiceImpl getThreeDLayoutPage(ThreeDLayoutQueryDTO query) { +// AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder(); + // 分页数据 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.lambda().eq(ThreeDLayout::getType, "front"); + queryWrapper.lambda().eq(ThreeDLayout::getGender, "female"); + IPage page = threeDLayoutMapper.selectPage( + new Page<>(query.getPage(), query.getSize()), queryWrapper); + if (CollectionUtils.isEmpty(page.getRecords())) { + return new Page<>(); + } + + IPage convert = page.convert((Function) threeDLayout -> { + if (threeDLayout != null) { + ThreeDLayoutVO threeDLayoutVO = CopyUtil.copyObject(threeDLayout, ThreeDLayoutVO.class); + threeDLayoutVO.setUrl(minioUtil.getPreSignedUrl(threeDLayoutVO.getUrl(), 24 * 60)); + return threeDLayoutVO; + } + return null; + }); + return convert; + } + + @Override + public ThreeDVO getLayoutDetail(Long threeDSimpleId) { + ThreeDVO result = new ThreeDVO(); + + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(ThreeDLayout::getThreeDSimpleId, threeDSimpleId); + List threeDLayoutList = threeDLayoutMapper.selectList(qw); + result.setThreeDLayoutList(threeDLayoutList); + + QueryWrapper threeDPatternLayoutQueryWrapper = new QueryWrapper<>(); + threeDPatternLayoutQueryWrapper.lambda().eq(ThreeDPatternLayout::getThreeDSimpleId, threeDSimpleId); + List threeDPatternLayoutList = threeDPatternLayoutMapper.selectList(threeDPatternLayoutQueryWrapper); + if (CollectionUtil.isNotEmpty(threeDPatternLayoutList)) { + result.setThreeDPatternLayout(threeDPatternLayoutList.get(0)); + } + return result; + } + + @Override + public ThreeDSizeVO getThreeDSize(Long threeDSimpleId) { + ThreeDSizeVO result = new ThreeDSizeVO(); + QueryWrapper threeDDetailQueryWrapper = new QueryWrapper<>(); + threeDDetailQueryWrapper.lambda().eq(ThreeDDetail::getThreeDSimpleId, threeDSimpleId); + List threeDDetailList = threeDDetailMapper.selectList(threeDDetailQueryWrapper); + if (CollectionUtil.isNotEmpty(threeDDetailList)) { + // 以 sizeType 分组 + Map> sizeTypeMap = new HashMap<>(); + for (ThreeDDetail detail : threeDDetailList) { + sizeTypeMap + .computeIfAbsent(detail.getSizeType(), k -> new ArrayList<>()) + .add(detail.getSize()); + } + result.setSizeTypeMap(sizeTypeMap); + } + return result; + } + + @Override + public void getThreeDGlb(Long threeDSimpleId, HttpServletResponse response) throws MinioException, IOException { + ThreeDSimple threeDSimple = threeDSimpleMapper.selectById(threeDSimpleId); + if (ObjectUtils.isAllFieldNull(threeDSimple)) { + throw new BusinessException("3D file is not exist"); + } + InputStream inputStream = minioUtil.download(threeDSimple.getUrl()); + + // 设置响应头 + response.setContentType("model/gltf-binary"); // 确保 MIME 类型正确 + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); + response.setHeader("Content-Disposition", "attachment; filename=\"" + threeDSimple.getName() + "\""); + + // 将文件内容写入响应输出流 + try { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + response.getOutputStream().write(buffer, 0, bytesRead); + } + inputStream.close(); + response.getOutputStream().flush(); + } catch (Exception e) { + throw new RuntimeException("Failed to get 3D .glb file", e); + } + } + + @Override + public void downloadZip(Long threeDSimpleId, String sizeType, String size, HttpServletResponse response) throws MinioException, IOException { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(ThreeDDetail::getThreeDSimpleId, threeDSimpleId); + qw.lambda().eq(ThreeDDetail::getSizeType, sizeType); + qw.lambda().eq(ThreeDDetail::getSize, size); + ThreeDDetail threeDDetail = threeDDetailMapper.selectOne(qw); + if (ObjectUtils.isAllFieldNull(threeDDetail)) { + throw new BusinessException("3D file is not exist"); + } + InputStream inputStream = minioUtil.download(threeDDetail.getUrl()); + + // 设置响应头 + response.setContentType("application/zip"); // 确保 ZIP 格式 + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); + response.setHeader("Content-Disposition", "attachment; filename=\"" + threeDDetail.getName() + "\""); + + // 将文件内容写入响应输出流 + try { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + response.getOutputStream().write(buffer, 0, bytesRead); + } + inputStream.close(); + response.getOutputStream().flush(); + } catch (Exception e) { + throw new RuntimeException("Failed to download ZIP file", e); + } + } }