下载商品按照快照状态下载
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -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='订单商品图片快照表';
|
||||
|
||||
Reference in New Issue
Block a user