diff --git a/src/main/java/com/aida/seller/module/listing/controller/ListingMallController.java b/src/main/java/com/aida/seller/module/listing/controller/ListingMallController.java index 6922d3c..1266e6b 100644 --- a/src/main/java/com/aida/seller/module/listing/controller/ListingMallController.java +++ b/src/main/java/com/aida/seller/module/listing/controller/ListingMallController.java @@ -50,11 +50,12 @@ public class ListingMallController { return Response.success(result); } - @Operation(summary = "获取商品 listing 图片 URL 列表", description = "返回指定商品ID的 listing 分类图片 URL 列表") + @Operation(summary = "获取商品 listing 图片 URL 列表", description = "返回指定商品ID的 listing 分类图片 URL 列表(仅返回已购买该商品的用户)") @GetMapping("/mall/main-product/urls") public Response> getListingUrls( - @Parameter(description = "商品ID") @RequestParam Long id) { - List urls = listingMallService.getListingUrls(id); + @Parameter(description = "商品ID") @RequestParam Long id, + @Parameter(description = "买家ID") @RequestParam Long buyerId) { + List urls = listingMallService.getListingUrls(id, buyerId); return Response.success(urls); } } diff --git a/src/main/java/com/aida/seller/module/listing/service/ListingMallService.java b/src/main/java/com/aida/seller/module/listing/service/ListingMallService.java index a85f3f9..20f67f1 100644 --- a/src/main/java/com/aida/seller/module/listing/service/ListingMallService.java +++ b/src/main/java/com/aida/seller/module/listing/service/ListingMallService.java @@ -40,7 +40,8 @@ public interface ListingMallService { * 获取商品的 listing 图片 URL 列表 * * @param id 商品ID + * @param buyerId 买家ID * @return listing 图片 URL 列表 */ - List getListingUrls(Long id); + List getListingUrls(Long id, Long buyerId); } diff --git a/src/main/java/com/aida/seller/module/listing/service/impl/ListingMallServiceImpl.java b/src/main/java/com/aida/seller/module/listing/service/impl/ListingMallServiceImpl.java index e5b8367..9a63984 100644 --- a/src/main/java/com/aida/seller/module/listing/service/impl/ListingMallServiceImpl.java +++ b/src/main/java/com/aida/seller/module/listing/service/impl/ListingMallServiceImpl.java @@ -8,10 +8,13 @@ import com.aida.seller.module.listing.dto.ListingMallQueryDTO; import com.aida.seller.module.listing.entity.ListingEntity; import com.aida.seller.module.listing.entity.ListingImageEntity; import com.aida.seller.module.listing.enums.DesignForEnum; +import com.aida.seller.module.listing.enums.ImageCategoryEnum; import com.aida.seller.module.listing.mapper.ListingImageMapper; import com.aida.seller.module.listing.mapper.ListingMallMapper; import com.aida.seller.module.listing.vo.ListingDetailVO; import com.aida.seller.module.listing.vo.ListingMallVO; +import com.aida.seller.module.order.entity.OrderItemImageEntity; +import com.aida.seller.module.order.mapper.OrderItemImageMapper; import com.aida.seller.util.MinioUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -37,11 +40,14 @@ public class ListingMallServiceImpl extends ServiceImpl> imageMap = images.stream() .filter(img -> StringUtils.hasText(img.getCategory())) + // hasSelection == true 的类别只保留 isSelected == 1 的图片 + .filter(img -> { + ImageCategoryEnum categoryEnum = ImageCategoryEnum.of(img.getCategory()); + return categoryEnum == null || !categoryEnum.isHasSelection() || Integer.valueOf(1).equals(img.getIsSelected()); + }) // 先按 category 分组,再按 sortOrder 组内排序,确保同组图片按 sortOrder 升序排列 .sorted(Comparator.comparing(ListingImageEntity::getCategory) .thenComparing(ListingImageEntity::getSortOrder, Comparator.nullsLast(Comparator.naturalOrder()))) @@ -208,26 +219,21 @@ public class ListingMallServiceImpl extends ServiceImpl getListingUrls(Long id) { - List images = listingImageMapper.selectList( - new LambdaQueryWrapper() - .eq(ListingImageEntity::getListingId, id) - .orderByAsc(ListingImageEntity::getSortOrder)); + public List getListingUrls(Long id, Long buyerId) { + List snapshots = orderItemImageMapper + .selectByListingIdAndBuyerIdWithOrderStatus(id, buyerId); - Map> imageMap = images.stream() - .filter(img -> StringUtils.hasText(img.getCategory())) - .sorted(Comparator.comparing(ListingImageEntity::getCategory) - .thenComparing(ListingImageEntity::getSortOrder, Comparator.nullsLast(Comparator.naturalOrder()))) - .collect(Collectors.groupingBy( - ListingImageEntity::getCategory, - Collectors.mapping(ListingImageEntity::getImageUrl, Collectors.toList()) - )); + if (snapshots.isEmpty()) { + throw new BusinessException("该商品尚未被购买,无法查看"); + } - return imageMap.entrySet().stream() - .filter(entry -> !entry.getKey().equals("firstFrame") && !entry.getKey().equals("gif")) - .flatMap(entry -> entry.getValue().stream()) - .distinct() - .toList(); + return snapshots.stream() + .filter(img -> !ImageCategoryEnum.GIF.getCode().equals(img.getCategory()) + && !ImageCategoryEnum.FIRST_FRAME.getCode().equals(img.getCategory()) + && !ImageCategoryEnum.VIDEO.getCode().equals(img.getCategory())) + .sorted(Comparator.comparing(OrderItemImageEntity::getSortOrder, Comparator.nullsLast(Comparator.naturalOrder()))) + .map(OrderItemImageEntity::getImageUrl) + .collect(Collectors.toList()); } @Override diff --git a/src/main/java/com/aida/seller/module/order/entity/OrderItemImageEntity.java b/src/main/java/com/aida/seller/module/order/entity/OrderItemImageEntity.java new file mode 100644 index 0000000..980de0c --- /dev/null +++ b/src/main/java/com/aida/seller/module/order/entity/OrderItemImageEntity.java @@ -0,0 +1,56 @@ +package com.aida.seller.module.order.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 订单商品图片快照表 + */ +@Data +@TableName("seller_order_item_image") +public class OrderItemImageEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 主键ID */ + @TableId(type = IdType.ASSIGN_ID) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** 订单商品ID(关联 seller_order_item.id) */ + @JsonSerialize(using = ToStringSerializer.class) + private Long orderItemId; + + /** 订单ID */ + @JsonSerialize(using = ToStringSerializer.class) + private Long orderId; + + /** 原商品ID(留作参考) */ + @JsonSerialize(using = ToStringSerializer.class) + private Long listingId; + + /** 买家ID */ + private Long buyerId; + + /** 图片类别:cover / main_product / product / sketch / apparel / firstFrame / gif / video */ + private String category; + + /** 图片URL */ + private String imageUrl; + + /** 排序 */ + private Integer sortOrder; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 是否删除:0-否,1-是 */ + @TableLogic + private Integer deleted; +} diff --git a/src/main/java/com/aida/seller/module/order/mapper/OrderItemImageMapper.java b/src/main/java/com/aida/seller/module/order/mapper/OrderItemImageMapper.java new file mode 100644 index 0000000..8e8192e --- /dev/null +++ b/src/main/java/com/aida/seller/module/order/mapper/OrderItemImageMapper.java @@ -0,0 +1,19 @@ +package com.aida.seller.module.order.mapper; + +import com.aida.seller.module.order.entity.OrderItemImageEntity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 订单商品图片快照 Mapper + */ +@Mapper +public interface OrderItemImageMapper extends BaseMapper { + + List selectByListingIdAndBuyerIdWithOrderStatus( + @Param("listingId") Long listingId, + @Param("buyerId") Long buyerId); +} diff --git a/src/main/java/com/aida/seller/module/order/service/OrderServiceImpl.java b/src/main/java/com/aida/seller/module/order/service/OrderServiceImpl.java index d169395..22555b8 100644 --- a/src/main/java/com/aida/seller/module/order/service/OrderServiceImpl.java +++ b/src/main/java/com/aida/seller/module/order/service/OrderServiceImpl.java @@ -6,6 +6,9 @@ import com.aida.seller.common.exception.BusinessException; import com.aida.seller.module.designer.entity.DesignerEntity; import com.aida.seller.module.designer.mapper.DesignerMapper; import com.aida.seller.module.listing.entity.ListingEntity; +import com.aida.seller.module.listing.entity.ListingImageEntity; +import com.aida.seller.module.listing.enums.ImageCategoryEnum; +import com.aida.seller.module.listing.mapper.ListingImageMapper; import com.aida.seller.module.listing.mapper.ListingMapper; import com.aida.seller.module.order.dto.AssetsDTO; import com.aida.seller.module.order.dto.CreateOrderDTO; @@ -14,7 +17,9 @@ import com.aida.seller.module.order.dto.UpdateOrderStatusDTO; import com.aida.seller.module.order.dto.BuyerOrdersDTO; import com.aida.seller.module.order.entity.OrderInfoEntity; import com.aida.seller.module.order.entity.OrderItemEntity; +import com.aida.seller.module.order.entity.OrderItemImageEntity; import com.aida.seller.module.order.mapper.OrderInfoMapper; +import com.aida.seller.module.order.mapper.OrderItemImageMapper; import com.aida.seller.module.order.mapper.OrderItemMapper; import com.aida.seller.module.order.vo.AssetsItemVO; import com.aida.seller.module.order.vo.BuyerOrderItemVO; @@ -51,6 +56,8 @@ import java.util.stream.Collectors; public class OrderServiceImpl extends ServiceImpl implements OrderService { private final OrderItemMapper orderItemMapper; + private final OrderItemImageMapper orderItemImageMapper; + private final ListingImageMapper listingImageMapper; private final MinioUtil minioUtil; private final ListingMapper listingMapper; private final DesignerMapper designerMapper; @@ -283,6 +290,30 @@ public class OrderServiceImpl extends ServiceImpl images = listingImageMapper.selectList( + new LambdaQueryWrapper() + .eq(ListingImageEntity::getListingId, listing.getId())); + List snapshots = images.stream() + .filter(img -> { + ImageCategoryEnum categoryEnum = ImageCategoryEnum.of(img.getCategory()); + return categoryEnum == null || !categoryEnum.isHasSelection() || Integer.valueOf(1).equals(img.getIsSelected()); + }) + .map(img -> { + OrderItemImageEntity snap = new OrderItemImageEntity(); + snap.setOrderItemId(item.getId()); + snap.setOrderId(order.getId()); + snap.setListingId(listing.getId()); + snap.setBuyerId(dto.getBuyerId()); + snap.setCategory(img.getCategory()); + snap.setImageUrl(img.getImageUrl()); + snap.setSortOrder(img.getSortOrder()); + return snap; + }) + .collect(Collectors.toList()); + if (!snapshots.isEmpty()) { + orderItemImageMapper.insert(snapshots); + } } orderIds.add(order.getId()); diff --git a/src/main/resources/db/schema.sql b/src/main/resources/db/schema.sql index 8b8f13f..8bf0b16 100644 --- a/src/main/resources/db/schema.sql +++ b/src/main/resources/db/schema.sql @@ -97,3 +97,18 @@ CREATE TABLE seller_order_item ( INDEX idx_listing_id (listing_id), INDEX idx_deleted (deleted) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单商品明细表'; + +-- 订单商品图片快照表 +CREATE TABLE seller_order_item_image ( + id BIGINT PRIMARY KEY COMMENT '主键ID', + order_item_id BIGINT NOT NULL COMMENT '订单商品ID', + order_id BIGINT COMMENT '订单ID', + listing_id BIGINT COMMENT '原商品ID', + buyer_id BIGINT COMMENT '买家ID', + category VARCHAR(32) COMMENT '图片类别', + image_url VARCHAR(512) COMMENT '图片URL', + sort_order INT DEFAULT 0 COMMENT '排序', + create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + deleted INT(1) DEFAULT 0 COMMENT '是否删除:0-否,1-是', + INDEX idx_listing_buyer (listing_id, buyer_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单商品图片快照表';