下载商品按照快照状态下载

This commit is contained in:
litianxiang
2026-06-01 11:30:02 +08:00
parent 269db8a060
commit 51491e4493
7 changed files with 152 additions and 23 deletions

View File

@@ -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<List<String>> getListingUrls(
@Parameter(description = "商品ID") @RequestParam Long id) {
List<String> urls = listingMallService.getListingUrls(id);
@Parameter(description = "商品ID") @RequestParam Long id,
@Parameter(description = "买家ID") @RequestParam Long buyerId) {
List<String> urls = listingMallService.getListingUrls(id, buyerId);
return Response.success(urls);
}
}

View File

@@ -40,7 +40,8 @@ public interface ListingMallService {
* 获取商品的 listing 图片 URL 列表
*
* @param id 商品ID
* @param buyerId 买家ID
* @return listing 图片 URL 列表
*/
List<String> getListingUrls(Long id);
List<String> getListingUrls(Long id, Long buyerId);
}

View File

@@ -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<ListingMallMapper, Listi
private final MinioUtil minioUtil;
private final ListingImageMapper listingImageMapper;
private final DesignerMapper designerMapper;
private final OrderItemImageMapper orderItemImageMapper;
public ListingMallServiceImpl(MinioUtil minioUtil, ListingImageMapper listingImageMapper, DesignerMapper designerMapper) {
public ListingMallServiceImpl(MinioUtil minioUtil, ListingImageMapper listingImageMapper, DesignerMapper designerMapper,
OrderItemImageMapper orderItemImageMapper) {
this.minioUtil = minioUtil;
this.listingImageMapper = listingImageMapper;
this.designerMapper = designerMapper;
this.orderItemImageMapper = orderItemImageMapper;
}
@Override
@@ -166,6 +172,11 @@ public class ListingMallServiceImpl extends ServiceImpl<ListingMallMapper, Listi
Map<String, List<String>> 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<ListingMallMapper, Listi
}
@Override
public List<String> getListingUrls(Long id) {
List<ListingImageEntity> images = listingImageMapper.selectList(
new LambdaQueryWrapper<ListingImageEntity>()
.eq(ListingImageEntity::getListingId, id)
.orderByAsc(ListingImageEntity::getSortOrder));
public List<String> getListingUrls(Long id, Long buyerId) {
List<OrderItemImageEntity> snapshots = orderItemImageMapper
.selectByListingIdAndBuyerIdWithOrderStatus(id, buyerId);
Map<String, List<String>> 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

View File

@@ -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;
}

View File

@@ -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<OrderItemImageEntity> {
List<OrderItemImageEntity> selectByListingIdAndBuyerIdWithOrderStatus(
@Param("listingId") Long listingId,
@Param("buyerId") Long buyerId);
}

View File

@@ -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<OrderInfoMapper, OrderInfoEntity> 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<OrderInfoMapper, OrderInfoEnti
item.setPrice(listing.getPrice());
item.setProductCategory(listing.getProductCategory());
orderItemMapper.insert(item);
List<ListingImageEntity> images = listingImageMapper.selectList(
new LambdaQueryWrapper<ListingImageEntity>()
.eq(ListingImageEntity::getListingId, listing.getId()));
List<OrderItemImageEntity> 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());

View File

@@ -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='订单商品图片快照表';